【问题标题】:Angular2 Heros Tutorial - How does child component get Service/Provider?Angular2 Heros 教程 - 子组件如何获取 Service/Provider?
【发布时间】:2016-06-09 23:20:20
【问题描述】:

我现在正在学习 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)提供。这是准确的吗?

【问题讨论】:

    标签: angular


    【解决方案1】:

    From the tutorial:

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

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

    如果您多次实例化服务,了解该行为以避免错误实际上很重要,这可能不是您大多数时候想要的。


    更新了更多信息:

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

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

    【讨论】:

    • 是的,添加到这个答案:providers 数组与子组件共享实例,而viewProviders 数组只为该组件及其模板创建它。
    • 我认为文档不太正确。 providers 数组向组件的注入器注册了一个提供程序。创建 AppComponent 时不会创建 HeroService。它是在子组件注入它时创建的(在其构造函数中)。从this plunker 中删除&lt;child&gt;&lt;/child&gt;,您会看到没有创建服务实例,因为没有组件注入它。
    【解决方案2】:

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

    providers: [HeroService]
    

    这其实是一个简写的表达方式

    providers: [new Provider(HeroService, {useClass: HeroService})]
    

    本质上,我们向注入器注册了一个“配方”——即,当此组件或其后代之一注入 HeroService 时,我们告诉注入器如何创建 HeroService(即依赖项)。

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

    constructor(private heroService: HeroService)
    

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-04
      相关资源
      最近更新 更多