2016-04-18 55 views
2

我已經在官方Angular 2頁面上看過「英雄」教程,當我走到路由時,有幾件事情沒有意義。這是關於提供者。Angular 2 - 供應商如何實際工作?

有問題的部分表示如下。我的主要成分是這樣的:

/* app.components */ 
import {Component} from 'angular2/core'; 
import {HeroesComponent} from './heroes.component'; 
import {HeroService} from './hero.service'; 

@Component({ 
    selector: 'my-app', 
    template: ` 
     <h1>{{title}}</h1> 
     <my-heroes></my-heroes> 
    ` 
    directives: [HeroesComponent], 
    providers: [HeroService] 

}) 
export class AppComponent { 
    title = 'Tour of Heroes'; 
    constructor(private _heroService: HeroService) {} 
} 

和英雄的組件看起來是這樣的:

/* heroes.component */ 
import {Component} from 'angular2/core'; 
import {Hero} from './hero'; 
import {HeroDetailComponent} from './hero-detail.component'; 
import {HeroService} from './hero.service'; 
import {OnInit} from 'angular2/core'; 

@Component({ 
    selector: 'my-heroes', 
    directives: [HeroDetailComponent], 
    template: ` 
     <h2>My Heroes</h2> 
     <ul class="heroes"> 
      <li *ngFor="#hero of heroes" [class.selected] = "hero === selectedHero" (click)="onSelect(hero)"> 
       <span class="badge"> {{hero.id}} </span> {{hero.name}} 
      </li> 
     </ul> 
     <my-hero-detail [hero]="selectedHero"></my-hero-detail> 
     ` 
}) 
export class HeroesComponent implements OnInit { 
    heroes: Hero[]; 
    selectedHero: Hero; 
    ngOnInit() { 
     this.getHeroes(); 
    } 
    constructor(private _heroService: HeroService) { } 

    getHeroes() { 
     this._heroService.getHeroes().then(heroes => this.heroes = heroes); 
    } 

    onSelect(hero: Hero) { 
     this.selectedHero = hero; 
    } 

} 

OK,所以我的問題:爲了這個工作,我需要在這兩個文件中導入import {HeroService} from './hero.service'; 。但是,providers: [HeroService]僅是app.components@Component的一部分。我不需要在heroes.component中寫這段代碼。 heroes.component如何知道選擇哪個供應商?它是從app.components繼承嗎?如果是這樣,爲什麼我必須在這兩個文件中寫這個:import {HeroService} from './hero.service';?爲什麼不只是在app.components?這兩個類也有相同的constructor。我不知道這裏發生了什麼事情,所以先謝謝任何解釋。

回答

0

注射器是分層的。在bootstrap()中初始化根提供程序,然後爲每個組件創建另一個子注入器,這會導致在DOM中模擬您的組件的結構。

當Angular實例化一個類(service,component,pipe,...)時,它請求DI的一個實例,DI也嘗試解析構造函數參數。這是遞歸地完成,直到沒有進一步的依賴需要解決,然後返回實例。

從最近的噴油器請求一個實例。如果注射器沒有類型的提供者(或其他鍵如字符串或OpaqueToken),則將請求轉發給父注入器,直至找到提供者或到達根注入器。

欲瞭解更多詳情,請參閱https://angular.io/docs/ts/latest/api/core/Directive-decorator.html

0

在研究了Angular-2的一些文檔後,我分享了關於dependency-injection and providers的知識,可以幫助某人。

依賴注入是分層的, 依賴注入是一個重要的應用程序設計圖案。Angular擁有自己的依賴注入框架,如果沒有它,我們確實無法構建一個Angular應用程序。

相關性是噴油器範圍內的單例。在我們的示例中,AppComponent及其HeroComponent兒童共享一個HeroService實例。在您的示例中,AppComponent是英雄功能區的根組件。它管轄着這個地區的所有兒童組成部分。 Yur HeroService可能會公開一個返回heros數據的getHeroes方法,但它的所有消費者都不需要知道這一點。

服務無非是角2類以上,直到我們有角 噴油器進行註冊它仍然 無非類的更多。

這就是爲什麼您需要配置噴油器。我們不必創建一個Angular注入器。 Angular在引導過程中爲我們創建了一個應用程序範圍內的注入器。我們必須通過註冊提供商來配置注入器,以創建我們應用程序所需的服務。我們可以在引導過程中註冊提供者。如:

bootstrap(AppComponent, 
     [HeroService]); // DISCOURAGED (but works) 

注射器現在知道我們的HeroService。我們的HeroService的一個實例將可用於我們整個應用程序的注入。

首選的方法是在應用程序組件中註冊應用程序提供者。由於HeroService在英雄的特徵區域內使用,而在其他地方使用HeroService,因此註冊它的理想位置是頂級HeroesComponent

註冊商在組件

providers:[HeroService], // in your app.component that registers the HeroService 

仔細查看的@Component元數據的providers一部分。

HeroService的實例現在可用於注射在此 AppComponent及其所有子組件。

AppComponent本身並不需要HeroService。但是 其子小孩HeroComponent呢。

專注於構造

添加參數構造函數。

constructor(private _heroService: HeroService) { 
    this._heroService.getHeroes().then(heroes => this.heroes = heroes); // or you can use in OnInit 
} 

N.B:可能沒有必要在你的appComponent

我們正在寫打字稿,並且已經按照與 類型註釋,:HeroService參數名稱中使用constructor。該班也裝飾着 @Component裝飾。

當TypeScript編譯器評估此類時,它會看到裝飾器並將類元數據添加到生成的 JavaScript代碼中。其中元數據隱藏了 將heroService參數與HeroService類相關聯的信息。

這就是角柱塞如何在創建新的HeroComponent時知道如何注入 HeroService的實例。

更多細節依賴注入可以看到this link

和分層依賴注入可以看到this link