[Angular 大師之路] 認識 InjectionToken
在 Angular 中不是只有 service 可以當 token 被注入,我們也可以單純的注入某個物件,這個物件通常是一個全域的系統設定,或是單純的一個函數(function),這時候就會遇到一些問題,我們今天就來看看問題是什麼,以及如何解決!
類型:觀念
難度:4 顆星
實用度:5 顆星
一般情境
可以用我們之前學過的 useValue
,類似以下程式:
export class Config {
LogLevel: string
}
@NgModule({
providers: [
{
provide: Config,
useValue: { LogLevel: 'Error' }
}
]
})
export class AppModule { }
這完全不是問題,但如果不想宣告成 class
(畢竟會產生實際程式碼) 或是設定的不是物件,而是數值或字串呢?就會出問題了:
export interface Config {
LogLevel: string
}
@NgModule({
providers: [
{
// 錯誤,因為 interface 不會產生實體
provide: Config,
useValue: { LogLevel: 'Error' }
}
]
})
export class AppModule { }
這時候可以使用 Angular 提供的 InjectionToken
來強制幫我們產生一個 token
使用 InjectionToken
import { InjectionToken } from '@angular/core';
export interface Config {
LogLevel: string
}
// 替 interface 產生一個 token
// 參數的字串只是一個描述
export const CONFIG_TOKEN = new InjectionToken<Config>('config token');
// 基礎型別也不是問題
export const NAME_TOKEN = new InjectionToken<string>('name token');
@NgModule({
providers: [
{
provide: CONFIG_TOKEN,
useValue: { LogLevel: 'Error' }
},
{
provide: NAME_TOKEN,
useValue: 'Mike'
}
]
})
export class AppModule { }
至於要如何取得 token 實體呢?可以使用 @Inject()
裝飾器,來告知要使用哪個 token 注入:
constructor(@Inject(CONFIG_TOKEN) private config: Config) {
console.log(config);
}
Tree-shakable InjectionToken
InjectionToken
是非常特別的存在,通常都是提供給使用某個套件的人一些從外部設定的資訊,因此很多時候我們並不一定會去設定這個 token,但偏偏 InjectionToken
會真的產生實體,導致在進行 tree shaking 時無法過濾掉,跟傳統建立 service 的問題很類似,因此在 Angular 6 之後,也透過 providedIn: 'root'
的方法,來進行過濾:
const CONFIG_TOKEN = new InjectionToken<Config>('config token',
{
providedIn: 'root',
factory: () => ({
LogLevel: 'Error'
})
}
);
透過這種方式,當程式中有使用到 CONFIG_TOKEN
時,就會使用 factory: () => {}
產生的內容;若需要調整 token 的實體,在 @NgModule
的 providers: []
設定即可;而當完全沒有使用 CONFIG_TOKEN
時,這個被產生的內容也可以被過濾掉啦!
相關資源
如果您覺得我的文章有幫助,歡迎免費成為 LikeCoin 會員,幫我的文章拍手 5 次表示支持!