本系列教程的開發(fā)環(huán)境及開發(fā)語言:
在 Angular 中我們通過 Provider
來描述與 Token
相關(guān)聯(lián)的依賴對(duì)象的創(chuàng)建方式。在 Angular 中依賴對(duì)象的創(chuàng)建方式分為以下四種:
(圖一:注入器、Provider與依賴對(duì)象關(guān)系)
在 Angular 中 Provider
主要分為:
export interface ClassProvider {
// 用于設(shè)置與依賴對(duì)象關(guān)聯(lián)的Token值,Token值可能是Type、InjectionToken、
// OpaqueToken的實(shí)例或字符串
provide: any;
useClass: Type<any>;
// 用于標(biāo)識(shí)是否multiple providers,若是multiple類型,則返回與Token關(guān)聯(lián)的依賴
// 對(duì)象列表
multi?: boolean;
}
看完上面的接口定義,相信一些讀者會(huì)覺得陌生。在本系列教程第二小節(jié)中,我們用到了 TypeProvider
。不信你往下看:
@NgModule({
...
providers: [HeroService], // 方式一
bootstrap: [AppComponent]
})
export class AppModule { }
// TypeProvider接口
export interface TypeProvider extends Type<any> {}
那跟 ClassProvider
有什么關(guān)系?先不急,請(qǐng)你繼續(xù)往下看:
@NgModule({
...
providers: [{
provide: HeroService, useClass: HeroService // 方式二
}],
bootstrap: [AppComponent]
})
export class AppModule { }
是不是終于看到了 useClass
。其實(shí)上面兩種方式是等價(jià)的,方式一更加簡潔,方式二是采用標(biāo)準(zhǔn)的語法哈。那么問題來了,什么時(shí)候要使用 useClass
語法?回答這個(gè)問題前,我們先看個(gè)需求。
假設(shè)由于業(yè)務(wù)需要,先前我們定義的 HeroService
的數(shù)據(jù),需要從服務(wù)器獲取,而不是使用靜態(tài)數(shù)據(jù)。項(xiàng)目采用前后端分離的開發(fā)方式進(jìn)行開發(fā),此外在項(xiàng)目開發(fā)前已經(jīng)協(xié)商好數(shù)據(jù)格式,也給出了對(duì)應(yīng)的模擬數(shù)據(jù)(測試數(shù)據(jù))。
那么除了修改原有的 HeroService
服務(wù)外,有沒有其它方式可以方便地驗(yàn)證一下模擬數(shù)據(jù),同時(shí)保持較小的改動(dòng)量哈。其實(shí)我們可以創(chuàng)建一個(gè)新的數(shù)據(jù)服務(wù),如 MockHeroService
,具體實(shí)現(xiàn)如下:
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 { }
更新完相關(guān)的代碼,正常情況下,在 http://localhost:4200/
頁面,你將看到以下的內(nèi)容:
ID: 16 - Name: RubberMan
ID: 17 - Name: Dynama
ID: 18 - Name: Dr IQ
ID: 19 - Name: Magma
ID: 20 - Name: Tornado
其實(shí)服務(wù)命名為 MockHeroService
的目的,也是為了說明依賴注入的好處,即易于進(jìn)行本地單元測試。此外假設(shè)沒有利用 Angular 依賴注入的特性,我們需要修改應(yīng)用中每個(gè)應(yīng)用到 HeroService
的地方。
export interface Type<T> extends Function { new (...args: any[]): T; }
export function isType(v: any): v is Type<any> {
return typeof v === 'function';
}
更多建議: