https://code-examples.net/zh-CN/q/253af47
angular中國 (4)
我有一組angular2組件,應該都會注入一些服務。 我的第一個想法是,最好創建一個超級類並在那裏注入服務。 然後我的任何組件都會擴展該超類,但這種方法不起作用。
簡化示例:
export class AbstractComponent {
constructor(private myservice: MyService) {
// Inject the service I need for all components
}
}
export MyComponent extends AbstractComponent {
constructor(private anotherService: AnotherService) {
super(); // This gives an error as super constructor needs an argument
}
}
我可以通過在每個組件中注入 MyService
並使用該參數進行 super()
調用來解決這個問題,但這肯定是某種荒謬的。
如何正確組織我的組件,以便他們從超類繼承服務?
我可以通過在每個組件中注入MyService並使用該參數進行super()調用來解決這個問題,但這肯定是某種荒謬的。
這並不荒謬。 這是構造函數和構造函數注入的工作原理。
每個可注入類都必須將依賴項聲明爲構造函數參數,如果超類也具有依賴項,則這些類也需要在子類的構造函數中列出,並通過 super(dep1, dep2)
調用傳遞給超類。
繞過注射器並獲得依賴性勢在必行具有嚴重的缺點。
它隱藏了使代碼難以閱讀的依賴關係。
它違反了一個熟悉Angular2 DI如何工作的人的期望。
它打破了離線編譯,生成靜態代碼以替換聲明性和命令性DI,以提高性能並減少代碼大小。
如果已從第三方插件獲取父類(並且您無法更改源),則可以執行以下操作:
import { Injector } from '@angular/core';
export MyComponent extends AbstractComponent {
constructor(
protected injector: Injector,
private anotherService: AnotherService
) {
super(injector.get(MyService));
}
}
或者更好的方法(在構造函數中只保留一個參數):
import { Injector } from '@angular/core';
export MyComponent extends AbstractComponent {
private anotherService: AnotherService;
constructor(
protected injector: Injector
) {
super(injector.get(MyService));
this.anotherService = injector.get(AnotherService);
}
}
更新的解決方案,通過使用全局注入器來防止生成myService的多個實例。
import {Injector} from '@angular/core';
import {MyServiceA} from './myServiceA';
import {MyServiceB} from './myServiceB';
import {MyServiceC} from './myServiceC';
export class AbstractComponent {
protected myServiceA:MyServiceA;
protected myServiceB:MyServiceB;
protected myServiceC:MyServiceC;
constructor(injector: Injector) {
this.settingsServiceA = injector.get(MyServiceA);
this.settingsServiceB = injector.get(MyServiceB);
this.settingsServiceB = injector.get(MyServiceC);
}
}
export MyComponent extends AbstractComponent {
constructor(
private anotherService: AnotherService,
injector: Injector
) {
super(injector);
this.myServiceA.JustCallSomeMethod();
this.myServiceB.JustCallAnotherMethod();
this.myServiceC.JustOneMoreMethod();
}
}
這將確保MyService可以在任何擴展AbstractComponent的類中使用,而無需在每個派生類中注入MyService。
這個解決方案有一些缺點(請參閱我原始問題下面的@GünterZöchbauer的Ccomment):
- 當有許多不同的服務需要在許多地方注入時,注入全局注入器只是一種改進。 如果您只有一個共享服務,那麼在派生類中注入該服務可能更好/更容易
- 我的解決方案和他提議的替代方案都有缺點,它們使得更難以確定哪個類依賴於什麼服務。
有關Angular2中依賴注入的書面解釋,請參閱此博客文章,這有助於我解決問題: http://blog.thoughtram.io/angular/2015/05/18/dependency-injection-in-angular-2.html : http://blog.thoughtram.io/angular/2015/05/18/dependency-injection-in-angular-2.html
根據我的理解,爲了從基類繼承,首先需要實例化它。 爲了實例化它,你需要傳遞它的構造函數所需的參數,因此你通過super()調用將它們從子節點傳遞給父節點,這樣纔有意義。 注射器當然是另一種可行的解決方案。