Angular 4 依賴注入教程之三 ClassProvider的使用github
Angular 4 依賴注入教程之四 FactoryProvider的使用typescript
Angular 4 依賴注入教程之六 Injectable 裝飾器bootstrap
Angular 4 依賴注入教程之七 ValueProvider的使用segmentfault
本系列教程的開發環境及開發語言:服務器
在 Angular 中咱們經過 Provider
來描述與 Token
相關聯的依賴對象的建立方式。在 Angular 中依賴對象的建立方式分爲如下四種:
useClass
useValue
useExisting
useFactory
(圖一:注入器、Provider與依賴對象關係)
在 Angular 中 Provider
主要分爲:
TypeProvider
ClassProvider
ValueProvider
ExistingProvider
FactoryProvider
export interface ClassProvider { // 用於設置與依賴對象關聯的Token值,Token值多是Type、InjectionToken、 // OpaqueToken的實例或字符串 provide: any; useClass: Type<any>; // 用於標識是否multiple providers,如果multiple類型,則返回與Token關聯的依賴 // 對象列表 multi?: boolean; }
看完上面的接口定義,相信一些讀者會以爲陌生。在本系列教程第二小節中,咱們用到了 TypeProvider
。不信你往下看:
@NgModule({ ... providers: [HeroService], // 方式一 bootstrap: [AppComponent] }) export class AppModule { } // TypeProvider接口 export interface TypeProvider extends Type<any> {}
那跟 ClassProvider
有什麼關係?先不急,請你繼續往下看:
@NgModule({ ... providers: [{ provide: HeroService, useClass: HeroService // 方式二 }], bootstrap: [AppComponent] }) export class AppModule { }
是否是終於看到了 useClass
。其實上面兩種方式是等價的,方式一更加簡潔,方式二是採用標準的語法哈。那麼問題來了,何時要使用 useClass
語法?回答這個問題前,咱們先看個需求。
假設因爲業務須要,先前咱們定義的 HeroService
的數據,須要從服務器獲取,而不是使用靜態數據。項目採用先後端分離的開發方式進行開發,此外在項目開發前已經協商好數據格式,也給出了對應的模擬數據(測試數據)。
那麼除了修改原有的 HeroService
服務外,有沒有其它方式能夠方便地驗證一下模擬數據,同時保持較小的改動量哈。其實咱們能夠建立一個新的數據服務,如 MockHeroService
,具體實現以下:
export class MockHeroService { heros: Array<{ id: number; name: string }> = [ { id: 16, name: 'RubberMan' }, { id: 17, name: 'Dynama' }, { id: 18, name: 'Dr IQ' }, { id: 19, name: 'Magma' }, { id: 20, name: 'Tornado' } ]; getHeros() { return this.heros; } }
@NgModule({ ... providers: [{ provide: HeroService, useClass: MockHeroService }], bootstrap: [AppComponent] }) export class AppModule { }
更新完相關的代碼,正常狀況下,在 http://localhost:4200/
頁面,你將看到如下的內容:
ID: 16 - Name: RubberMan ID: 17 - Name: Dynama ID: 18 - Name: Dr IQ ID: 19 - Name: Magma ID: 20 - Name: Tornado
其實服務命名爲 MockHeroService
的目的,也是爲了說明依賴注入的好處,即易於進行本地單元測試。此外假設沒有利用 Angular 依賴注入的特性,咱們須要修改應用中每一個應用到 HeroService
的地方。
export interface Type<T> extends Function { new (...args: any[]): T; } export function isType(v: any): v is Type<any> { return typeof v === 'function'; }