有没有办法从父组件向组件注入服务?
Is there a way to inject a service into a component from the parent component?
所以我有一个 table 组件。但是 table 组件将需要使用适当的 API 服务,具体取决于它是由 ComponentA 还是 ComponentB 调用的。
例如,如果ComponentB使用了TableComponent,那么它需要让TableComponent注入APIForB服务,并用它来填充table.
angular 的新手,所以不确定这样的事情是否可行。
对你来说最好的方法是注入你的父组件并使用它的服务。为了简化注入和输入,您可以为所有这些 TableContaiers
创建一个超类
export abstract class TableContainer {
constructor(public apiService: SomeServiceTypeIfYouHaveIt) {};
}
..................
@Component({
...,
providers: [{provide: TableContainer, useExisting: ComponentA}]
})
export class ComponentA extends TableContainer {
constructor(service: MyService){ super(service); }
}
..................
export class TableComponent {
constructor(private parent: TableContainer) {}
apiCall() {
this.parent.apiService.doSmth();
}
}
那么 DI-system of angular is hierarchical 的意思是:
services are singletons within the scope of an injector
并且 Angular 将创建具有自己服务实例的嵌套注入器,每当它创建组件实例时,组件实例在其 @Component
装饰器中定义 providers
。
对您来说,这意味着您可以为您的组件提供不同的服务实现,这些服务实现必须扩展相同的抽象 class 并且您将抽象 class 注入到您的 TableComponent
:
API服务:
export abstract class APIService{
yourMethod1:() => void ;
...
}
您必须将基 class 定义为抽象 class 而不是接口,因为接口在运行时不存在,因此它们不是有效的 DI-Tokens。
APIforAService/APIforBService:
@Injectable()
export class APIforAService implements APIService{
youMethod1Implementation(){...}
....
}
当然,您对 APIforBService
执行相同的操作,但实现方式不同。
表格组件
现在在你的 TableComponent
中你注入 APIService
但没有定义提供者!
@Component({
selector: 'your-selector',
templateUrl: '',
providers: []
})
export class TableComponent {
constructor(private apiService: APIService) {
}
}
ComponentA/B
现在在 ComponentA 和 ComponentB 中定义适当的提供程序:
@Component({
selector: 'componentA',
templateUrl: '',
providers: [{
provide:APIService,
useClass:APIforAService
}]
})
export class ComponentA {
}
在这里你也对 ComponentB
做同样的事情并使用 APIforBService
.
由于分层 DI 系统,如果从 ComponentA
实例化,您的 TableComponent
得到 APIforAService
,如果从 ComponentB
[=29= 实例化,则得到 APIforBService
]
所以我有一个 table 组件。但是 table 组件将需要使用适当的 API 服务,具体取决于它是由 ComponentA 还是 ComponentB 调用的。
例如,如果ComponentB使用了TableComponent,那么它需要让TableComponent注入APIForB服务,并用它来填充table.
angular 的新手,所以不确定这样的事情是否可行。
对你来说最好的方法是注入你的父组件并使用它的服务。为了简化注入和输入,您可以为所有这些 TableContaiers
创建一个超类export abstract class TableContainer {
constructor(public apiService: SomeServiceTypeIfYouHaveIt) {};
}
..................
@Component({
...,
providers: [{provide: TableContainer, useExisting: ComponentA}]
})
export class ComponentA extends TableContainer {
constructor(service: MyService){ super(service); }
}
..................
export class TableComponent {
constructor(private parent: TableContainer) {}
apiCall() {
this.parent.apiService.doSmth();
}
}
那么 DI-system of angular is hierarchical 的意思是:
services are singletons within the scope of an injector
并且 Angular 将创建具有自己服务实例的嵌套注入器,每当它创建组件实例时,组件实例在其 @Component
装饰器中定义 providers
。
对您来说,这意味着您可以为您的组件提供不同的服务实现,这些服务实现必须扩展相同的抽象 class 并且您将抽象 class 注入到您的 TableComponent
:
API服务:
export abstract class APIService{
yourMethod1:() => void ;
...
}
您必须将基 class 定义为抽象 class 而不是接口,因为接口在运行时不存在,因此它们不是有效的 DI-Tokens。
APIforAService/APIforBService:
@Injectable()
export class APIforAService implements APIService{
youMethod1Implementation(){...}
....
}
当然,您对 APIforBService
执行相同的操作,但实现方式不同。
表格组件
现在在你的 TableComponent
中你注入 APIService
但没有定义提供者!
@Component({
selector: 'your-selector',
templateUrl: '',
providers: []
})
export class TableComponent {
constructor(private apiService: APIService) {
}
}
ComponentA/B
现在在 ComponentA 和 ComponentB 中定义适当的提供程序:
@Component({
selector: 'componentA',
templateUrl: '',
providers: [{
provide:APIService,
useClass:APIforAService
}]
})
export class ComponentA {
}
在这里你也对 ComponentB
做同样的事情并使用 APIforBService
.
由于分层 DI 系统,如果从 ComponentA
实例化,您的 TableComponent
得到 APIforAService
,如果从 ComponentB
[=29= 实例化,则得到 APIforBService
]