Angular2 Heros教程 - 子组件如何获得服务/提供者?

时间:2016-06-09 23:20:20

标签: angular

我现在正在阅读Angular2 Heros教程。

我具体是at this step

  

返回HeroesComponent并从其providers数组中删除HeroService。我们正在将这项服务从HeroesComponent推广到AppComponent。我们不希望在我们的应用程序的两个不同级别上提供此服务的两个副本。

app.comonent.ts:

import { Component } from '@angular/core';
import { HeroService } from './hero.service';
import { HeroesComponent } from './heroes.component';

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

})
export class AppComponent { 
    title = 'Main App';
}

heros.component.ts:

import { Component, OnInit } from '@angular/core';
import { Hero } from './hero';
import { HeroDetailComponent } from './hero-detail.component';
import { HeroService } from './hero.service';

@Component({
  selector: 'my-heroes',
  template: `
        ... bla bla bla ...
    `,

    styles:[`
          ... bla bla bla ...
    `],
    directives: [HeroDetailComponent],
    providers: [
        HeroService
    ]


})
export class HeroesComponent implements OnInit { 

    public heroes: Hero[];
    selectedHero: Hero;

    constructor(
        private heroService: HeroService
    ){}

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

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

我的问题是,当我从heros.components的Providers列表中删除HeroService时,为什么这仍然有用?

我的假设是,因为我们在构造函数中指定我们需要一个HeroService,一个将由父组件提供(在本例中为app.component)。这准确吗?

2 个答案:

答案 0 :(得分:5)

From the tutorial:

  

providers数组告诉Angular在创建新的AppComponent时创建一个新的HeroService实例。 AppComponent可以使用该服务来获取英雄,因此可以使用其组件树的每个子组件。

所以你的假设是部分正确的。 实际上,您的app.component会在子组件注入后立即创建一个服务实例。由于您的hero.componentapp.component的孩子,因此它将使用相同的实例。所以不是只有一个,而是那个

如果您多次实例化服务,那么知道该行为可以避免错误,这可能不是您想要的大部分时间。

更新了其他信息:

正如Mark Rajcok在他的评论中正确指出的那样,只要app.component的一个子组件注入它,就会创建该服务。如果没有子组件注入该服务,则不会创建该服务的实例。

正如Ed Morales补充的那样,通过使用viewProviders代替providers来提供服务还有另一种可能性,这将使得创建的实例只能由提供组件访问,而不是所有它的孩子。

答案 1 :(得分:3)

providers数组使用组件注入器注册类(或函数,或预定义对象或字符串)。例如,

providers: [HeroService]

这实际上是

的简写表达式
providers: [new Provider(HeroService, {useClass: HeroService})]

基本上我们注册了一个&#34;配方&#34;使用注入器 - 即,当该组件或其后代之一注入HeroService时,我们告诉注入器如何创建HeroService(即依赖)。

我们使用构造函数注入依赖项。例如,

constructor(private heroService: HeroService)

HeroesComponent注入HeroService时,Angular执行以下操作:

  • 首先查看请求组件的注入器(即HeroesComponent注入器)是否具有用于创建HeroService的配方。它没有(它不在它的providers数组中),所以它将组件树上升到它的父组件。
  • 然后检查父组件的注射器(即AppComponent注射器)是否具有用于创建HeroService的配方。确实如此。 AppComponent注入器然后执行以下操作:
    • 如果之前创建了HeroService的实例,则返回对它的引用。
    • 否则(即,这是注入/请求HeroService的第一个组件),它执行以下操作:
      • 它使用配方创建HeroService
      • 的实例
      • 它存储对它的引用(对于此依赖项的其他可能请求)。
      • 它将对它的引用返回给要求依赖的HeroesComponent

AppComponent的注射器只会创建HeroService的一个实例。该(一个)实例可以注入AppComponent和/或其任何后代。