前兩天我們學到了多種替換注入 token 內容的方法,今天我們來看看如何取得不同注入內容的方式:
類型:觀念
難度:4 顆星
實用度:3 顆星
建構式注入是我們最常使用的注入方式,也就是直接在建構式中宣告要注入的 token 實體,Angular 在看到這個 token 時,會根據我們的設定決定要對這個類別注入什麼樣的實體:
constructor(private dataService: DataService) { }
在建構式中宣告 private
是 TypeScript 提供的一種語法糖,以上的寫法相當於:
private dataService: DataService;
constructor(dataService: DataService) {
this.dataService = dataService;
}
透過這種方式,可以少寫一些程式碼,會比較簡單。
Angular 提供了一個 Injector ,透過其中的 get()
方法,可以幫助我們動態取得某個 token 的實體:
import { Injector } from '@angular/core';
constructor(private injector: Injector) {
const service = this.injector.get(DataService);
console.log(service.getData());
}
在元件越來越複雜,建構式要注入的內容越來越多時,使用 Injector
,透過 Injector
可以讓建構是看起來清爽一點!
當然,最理想的情況應該是把原件再拆開成更小的元件,所以這只是提供另外一種思考方向囉。
Injector
還提供了一個 create()
的靜態方法,透過這個方法,我們可以在程式中隨時動態產生一個新的 Injector
物件:
const injector = Injector.create({
providers: [
{
provide: DataService,
useClass: AdminService,
deps: []
}
]
});
const service = injector.get(DataService);
console.log(service.getData());
上面程式中,我們使用 Injector.create()
方法,來產生一個 Injector
物件,建立的參數跟在 @NgModule
中設定基本上一樣,但沒有簡易版的寫法,這點需要注意一下。接著我們就能夠這個物件的 get()
方法來取得 token 實體囉。
在 @Component
和 @Directive
中,都有提供 providers: []
的設定,在這裡面設定的 token 會被另外產生,而不會吃所屬模組的設定:
@Component({
...
providers: [
{
provide: DataService,
useClass: AdminService
}
]
})
export class AppComponent {
constructor(private dataService: DataService) {
console.log(dataService.getData());
}
}
透過這種方式,我們可以確保每次產生元件時都會建立新的實體,而不跟外部產生的實體共享資源!畢竟不是每個元件都需要 singleton 的!
不好意思
額外想問一下,有關 provider / injector / service 這三者的關係
是 provider 還是 injector 產生 service 的呢 ??
另外將 service 注入到 component 的是 provider 還是 injector ??
抱歉,不知道我有沒有表達好,因為這三個的主從關係或是誰管理誰的關係,一直沒有說搞很懂 > <
這樣解釋看看能不能讓您比較清楚:
providers: []
是用來設定注入資訊的injector
injector
是注入資訊的載體,因此我們可以使用 injector.get()
方法取得某個可以被注入的實體service
單純的是程式,只是他們的概念和實作都被設計成「可以被注入」的反過來解釋的話:
當然不是只有 service
可以被注入,太多東西都可以被注入了,這部分可以參考上兩篇文章說明如何設定要注入的內容
至於怎麼決定要注入什麼呢?就是 providers: []
要負責設定的
至於要怎麼注入呢?就是今天文章的重點,除了最常用的建構式注入外,使用 injector
也是其中的一種方法
希望這樣解釋對您的釐清會有幫助,如果還是覺得哪裡有問題,歡迎隨時提出 :)
感謝您!!! 上述的思路很清晰,讓我很好地了解與吸收^^
感覺又多懂了一些東西