【问题标题】:Declaring service instance inside constructor in Angular 2在Angular 2的构造函数中声明服务实例
【发布时间】:2017-06-02 14:04:40
【问题描述】:

我是 Angular 2 和 Typescript 的新手,并试图理解 DI。在我看到的所有代码中,我看到引用服务的变量被输入到构造函数中。这是为什么?为什么我们不能在构造函数之外而是在类中声明它?

考虑以下来自《英雄之旅》的代码,例如在 Angular 网站上:

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

@Component({
    moduleId: module.id,
    selector: 'my-dashboard',
    templateUrl: `dashboard.component.html`,
    styleUrls: ['dashboard.component.css']
})
export class DashboardComponent implements OnInit {

    heroes: Hero[] = [];

    constructor(private heroService: HeroService) { }

    ngOnInit(): void {
        this.heroService.getHeroes()
            .then(heroes => this.heroes = heroes.slice(1, 5));
    }
}

如果我像下面这样在构造函数之外声明 heroService,应用程序会抛出很多错误。

export class DashboardComponent implements OnInit {

    heroes: Hero[] = [];

    constructor() { }

    private heroService: HeroService;

    ngOnInit(): void {
        this.heroService.getHeroes()
            .then(heroes => this.heroes = heroes.slice(1, 5));
    }
}

据我了解,在构造函数之外编写它不会生成服务类HeroService 的实例,但为什么呢? (是 Angular 还是 TypeScript?)在这个例子中,Hero 也是一个类(虽然不是服务类,但在技术上仍然是一个类!),我们在构造函数之外声明了 heroes: Hero[] = [];,它可以工作.

【问题讨论】:

标签: angular typescript


【解决方案1】:

您在此处描述的是一种属性(setter)注入,理论上是可行的,但通常不建议将其视为不好的做法。

为了更好地理解这一点,您应该阅读有关构造函数注入以及为什么它优于其他类型的注入(如属性注入)的原因。

据我所知,Angular 还没有实现其他类型来强制开发人员使用最佳实践,这就是为什么你不能在构造函数之外使用它。

Angular 1 引用了这个doc,您可以阅读它以更深入地理解它。不用担心是以前的版本,这些是概念性的术语,与框架或语言无关,您可以阅读它以了解基础知识。

附:不要忘记在构造函数中使用 Typescript 中的变量(使用 private)会自动创建属性。因此,当您在构造函数中使用它时,Angular 会将其注入其中,Typescripts 会隐式创建一个字段,就像在您上次的 sn-p 中一样,并从构造函数参数初始化它。

【讨论】:

    【解决方案2】:

    Angular DI 检查构造函数参数,当 Angular DI 创建类的新实例(服务、组件、指令、管道)时,它会查找要传递给构造函数的匹配提供程序。

    因此,

    • 注入仅适用于由 DI 实例化的类

    • 只考虑构造函数参数进行注入

    【讨论】:

    • 考虑查看文档:它有据可查:angular.io/docs/ts/latest/guide/dependency-injection.html
    • @Günter Zöchbauer:如果是这样,那么在上面的代码中,为什么'heroes: Hero[] = [];'工作? (它在构造函数之外定义)。这里的“英雄”只是一个简单的类,没有在不同的文件中定义任何装饰器。这里的变量“英雄”是“英雄”类的实例还是其他什么?如果它是“英雄”类的新实例,那么它是如何在构造函数之外实例化的?
    • 这是一个基本的 TypeScript 功能。 heroes: Hero[] 声明了一个名为 heroes 类型为 Hero[] 的字段,= [] 分配了一个初始值(一个空数组)。这与 DI 或 Angular 没有任何关系。
    • @Günter Zöchbauer:接口不是更适合做这样的事情吗?因为这里没有创建任何“英雄”类的实例,只有它的类型。这是代码(angular.io/docs/ts/latest/tutorial/toh-pt3.html
    • 我自己对 TS 并没有那么深入。我知道接口在运行时被删除,它们仅用于静态分析,如果该类没有任何方法,那么它似乎也是一个类的分支。我不知道他们在这里使用类而不是接口的确切原因。
    猜你喜欢
    • 2016-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-31
    • 2015-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多