Angular 4 依賴注入教程之七 ValueProvider的使用

目錄

閱讀須知

本系列教程的開發(fā)環(huán)境及開發(fā)語言:

基礎(chǔ)知識(shí)

ValueProvider 的作用

ValueProvider 用于告訴 Injector (注入器),但使用 Token 獲取依賴對象時(shí)阵谚,則返回 useValue 指定的值伪货。

ValueProvider 的使用

const provider: ValueProvider = {provide: 'someToken', useValue: 'someValue'};

ValueProvider 接口

export interface ValueProvider {
  // 用于設(shè)置與依賴對象關(guān)聯(lián)的Token值监氢,Token值可能是Type钉凌、InjectionToken损同、
  // OpaqueToken的實(shí)例或字符串
  provide: any;
  // 設(shè)置注入的對象
  useValue: any;
  // 用于標(biāo)識(shí)是否multiple providers,若是multiple類型慈鸠,則返回與Token關(guān)聯(lián)的依賴
  // 對象列表
  multi?: boolean;
}

json-server 簡介

json-server 用于基于 JSON 數(shù)據(jù)快速地創(chuàng)建本地模擬的 REST API蓝谨。

json-server 的安裝

npm install -g json-server

json-server 的使用

json-server --watch db.json

Angular CLI 代理配置

創(chuàng)建 proxy.conf.json 文件

{
  "/heros": {
    "target": "http://localhost:3000",
    "secure": false
  }
}

更新 package.json 文件

{
  "scripts": {
    "start": "ng serve --proxy-config proxy.conf.json",
  }
}

ValueProvider

介紹完基礎(chǔ)知識(shí),我們馬上進(jìn)入正題青团。不知道大家是否還記得譬巫,在 "組件服務(wù)注入" 文章中提到的內(nèi)容:

難道一切就這么結(jié)束了,No督笆! No芦昔!別忘記了我們這節(jié)課的主題是介紹如何在組件中注入服務(wù)。在目前的 HeroComponent 組件胖腾,我們的英雄列表信息是固定的,在實(shí)際的開發(fā)場景中瘪松,一般需要從遠(yuǎn)程服務(wù)器獲取相應(yīng)的信息咸作。

接下來我們將重構(gòu)我們的 HeroService 服務(wù),從 API 接口中獲取英雄數(shù)據(jù)宵睦。要使用 Angular 的 Http 服務(wù)记罚,首先需要在 AppModule 模塊中導(dǎo)入 HttpModule ,然后在 HeroService 類的構(gòu)造函數(shù)中注入 Http 服務(wù)壳嚎。

更新 HeroService 服務(wù)

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';

import { LoggerService } from './logger.service';

@Injectable()
export class HeroService {
    constructor(private loggerService: LoggerService,
      private http: Http) { }

    apiUrl = 'http://localhost:4200/heros';

    getHeros(): Observable<Array<{ id: number; name: string }>> {
        this.loggerService.log('Fetching heros...');
        return this.http.get(this.apiUrl)
            .map(res => res.json())
    }
}

HeroService 服務(wù)中桐智,我們通過注入 Http 服務(wù)對象的 get() 方法發(fā)送 HTTP 請求末早,從而從 API 接口中獲取英雄的數(shù)據(jù)。

更新 HeroComponent 組件

import { Component, OnInit } from '@angular/core';
import { HeroService } from '../hero.service';
import { LoggerService } from '../logger.service';

@Component({
  selector: 'app-hero',
  template: `
    <ul>
      <li *ngFor="let hero of heros">
        ID: {{hero.id}} - Name: {{hero.name}}
      </li>
    </ul>
  `
})
export class HeroComponent implements OnInit {
  heros: Array<{ id: number; name: string }>;

  constructor(private heroService: HeroService,
    private loggerService: LoggerService) { }

  ngOnInit() {
    this.loggerService.log('Fetching heros...');
    this.heroService.getHeros()
      .subscribe(res => {
        this.heros = res;
      });
  }
}

更新完上述代碼说庭,成功保存后然磷,你會(huì)發(fā)現(xiàn) http://localhost:4200/ 頁面,一片空白刊驴。這就對了姿搜,因?yàn)槲覀冞€沒有啟動(dòng)本地的 json-server 服務(wù)器。接下來我們來配置并啟動(dòng)本地的 json-server 服務(wù)器:

創(chuàng)建 heros.json 文件

{
  "heros": [
    {"id":11,"name":"Mr. Nice"},
    {"id":12,"name":"Narco"},
    {"id":13,"name":"Bombasto"},
    {"id":14,"name":"Celeritas"},
    {"id":15,"name":"Magneta"}
 ]
}

啟動(dòng) json-server 服務(wù)器

json-server --watch heros.json

當(dāng)成功啟動(dòng) json-server 服務(wù)器捆憎,在命令行中舅柜,你將看到以下輸出信息:

\{^_^}/ hi!

Loading heros.json
Done

這表示本地 json-server 已經(jīng)成功啟動(dòng),此時(shí)重新刷新以下 http://localhost:4200/ 頁面躲惰,你將看到以下信息:

ID: 11 - Name: Mr. Nice
ID: 12 - Name: Narco
ID: 13 - Name: Bombasto
ID: 14 - Name: Celeritas
ID: 15 - Name: Magneta

程序終于又正常運(yùn)行了致份,但注意到 HeroService 服務(wù)中,我們通過以下方式定義 API 接口地址:

@Injectable()
export class HeroService {
  ...
  apiUrl = 'http://localhost:4200/heros';
}

這種方式有個(gè)問題础拨,假設(shè)其它服務(wù)也要使用該地址氮块,那么就得按照同樣的方式去定義 API 接口地址。另外假設(shè) API 接口地址需要更新太伊,那就需要修改多個(gè)地方雇锡。針對上述問題,我們可以使用 ValueProvider 來解決問題僚焦。

使用 ValueProvider

@NgModule({
   ...,
   providers: [
    {
      provide: 'apiUrl',
      useValue: 'http://localhost:4200/heros'
    }
   ],
  bootstrap: [AppComponent]
})
export class AppModule { }

更新 HeroService 服務(wù)

@Injectable()
export class HeroService {
    constructor(private loggerService: LoggerService,
        private http: Http,
        @Inject('apiUrl') private apiUrl) { }

    getHeros(): Observable<Array<{ id: number; name: string }>> {
        this.loggerService.log('Fetching heros...');
        return this.http.get(this.apiUrl)
            .map(res => res.json())
    }
}

HeroService 類的構(gòu)造函數(shù)中锰提,我們通過 @Inject('apiUrl') 方式,注入 apiUrlToken 對應(yīng)的依賴對象芳悲,即 'http://localhost:4200/heros' 立肘。為什么不能使用 private apiUrl: 'apiUrl' 的方式,希望讀者好好回憶一下名扛,之前我們介紹過的相關(guān)內(nèi)容谅年。

以上代碼成功運(yùn)行后,在 http://localhost:4200/ 頁面肮韧,我們將看到預(yù)期的結(jié)果:

ID: 11 - Name: Mr. Nice
ID: 12 - Name: Narco
ID: 13 - Name: Bombasto
ID: 14 - Name: Celeritas
ID: 15 - Name: Magneta

我有話說

為什么在構(gòu)造函數(shù)中融蹂,非 Type 類型的參數(shù)只能用 @Inject(Something) 的方式注入 ?

因?yàn)?Type 類型的對象弄企,會(huì)被 TypeScript 編譯器編譯超燃。即我們通過 class 關(guān)鍵字聲明的服務(wù),最終都會(huì)編譯成 ES5 的函數(shù)對象拘领。

在構(gòu)造函數(shù)中意乓,Type 類型的參數(shù)能用 @Inject(Type) 的方式注入么?

Type 類型的參數(shù)也能使用 @Inject(Type) 的方式注入约素,具體如下:

 constructor(@Inject(Http) private http) { }

同樣也可以使用以下方式:

constructor(@Inject(Http) private http: Http) { }

第一種方式雖然可以正常編譯届良,但 IDE 會(huì)有如下的提示信息:

[ts] Parameter 'http' implicitly has an 'any' type.

第二種方式笆凌,雖然 Angular 內(nèi)部會(huì)合并 design:paramtypes 與 parameters 內(nèi)的 metadata 信息,但本人覺得是有點(diǎn)冗余了士葫。 總而言之乞而,若果是 Type 類型的參數(shù),推薦使用下面的方式:

constructor(private http: Http) { }

若有興趣了解 Inject 裝飾器的詳細(xì)信息为障,請參考 Angular 2 Inject 這篇文章晦闰。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市鳍怨,隨后出現(xiàn)的幾起案子呻右,更是在濱河造成了極大的恐慌,老刑警劉巖鞋喇,帶你破解...
    沈念sama閱讀 222,729評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件声滥,死亡現(xiàn)場離奇詭異,居然都是意外死亡侦香,警方通過查閱死者的電腦和手機(jī)落塑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來罐韩,“玉大人憾赁,你說我怎么就攤上這事∩⒊常” “怎么了龙考?”我有些...
    開封第一講書人閱讀 169,461評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長矾睦。 經(jīng)常有香客問我晦款,道長,這世上最難降的妖魔是什么枚冗? 我笑而不...
    開封第一講書人閱讀 60,135評(píng)論 1 300
  • 正文 為了忘掉前任缓溅,我火速辦了婚禮,結(jié)果婚禮上赁温,老公的妹妹穿的比我還像新娘坛怪。我一直安慰自己,他們只是感情好股囊,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評(píng)論 6 398
  • 文/花漫 我一把揭開白布袜匿。 她就那樣靜靜地躺著,像睡著了一般毁涉。 火紅的嫁衣襯著肌膚如雪沉帮。 梳的紋絲不亂的頭發(fā)上锈死,一...
    開封第一講書人閱讀 52,736評(píng)論 1 312
  • 那天贫堰,我揣著相機(jī)與錄音穆壕,去河邊找鬼。 笑死其屏,一個(gè)胖子當(dāng)著我的面吹牛喇勋,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播偎行,決...
    沈念sama閱讀 41,179評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼川背,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蛤袒?” 一聲冷哼從身側(cè)響起熄云,我...
    開封第一講書人閱讀 40,124評(píng)論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎妙真,沒想到半個(gè)月后缴允,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,657評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡珍德,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評(píng)論 3 342
  • 正文 我和宋清朗相戀三年练般,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锈候。...
    茶點(diǎn)故事閱讀 40,872評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡薄料,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出泵琳,到底是詐尸還是另有隱情摄职,我是刑警寧澤,帶...
    沈念sama閱讀 36,533評(píng)論 5 351
  • 正文 年R本政府宣布虑稼,位于F島的核電站琳钉,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏蛛倦。R本人自食惡果不足惜歌懒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望溯壶。 院中可真熱鬧及皂,春花似錦、人聲如沸且改。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽又跛。三九已至碍拆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背感混。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評(píng)論 1 274
  • 我被黑心中介騙來泰國打工端幼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人弧满。 一個(gè)月前我還...
    沈念sama閱讀 49,304評(píng)論 3 379
  • 正文 我出身青樓婆跑,卻偏偏與公主長得像,于是被迫代替她去往敵國和親庭呜。 傳聞我的和親對象是個(gè)殘疾皇子滑进,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容