Angular 4:@Inject何时以及为什么在构造函数中使用?

时间:2017-11-01 07:55:24

标签: javascript angular constructor angular-material2

问题陈述

我正在学习Angular 4,而我偶然发现了@Inject中使用constructor的代码,我无法弄明白为什么......

代码和来源

我正在使用Angular 4 Material

代码来源: https://material.angular.io/components/dialog/overview

在代码中,他们正在注入MAT_DIALOG_DATA

constructor(public dialogRef: MatDialogRef<DialogOverviewExampleDialog>,
             @Inject(MAT_DIALOG_DATA) public data: any
           ) { }

任何人都可以详细说明它的含义以及我们应该在何时/何地进行此操作?

3 个答案:

答案 0 :(得分:8)

  

@Inject()手动机制,让Angular知道a   必须注入参数

import { Component, Inject } from '@angular/core';
import { ChatWidget } from '../components/chat-widget';

@Component({
  selector: 'app-root',
  template: `Encryption: {{ encryption }}`
})
export class AppComponent {
  encryption = this.chatWidget.chatSocket.encryption;

  constructor(@Inject(ChatWidget) private chatWidget) { }
}
     

在上面我们要求chatWidget成为单身人士Angular   通过致电与class符号ChatWidget相关联   @Inject(ChatWidget)。请注意我们正在使用,这一点非常重要   ChatWidget为其单例输入作为引用。   我们使用ChatWidget实例化任何东西,Angular确实如此   在幕后为我们所用

来自https://angular-2-training-book.rangle.io/handout/di/angular2/inject_and_injectable.html

答案 1 :(得分:6)

如果MAT_DIALOG_DATA是非工厂/类依赖项(例如您的配置的string),则通常使用@Inject

同时检查InjectionTokenhttps://angular.io/guide/dependency-injection#injectiontoken

  

为非类依赖项选择提供程序标记的一种解决方案是定义和使用InjectionToken

这里是一名掠夺者:http://plnkr.co/edit/GAsVdGfeRpASiBEy66Pu?p=preview

如果您在这些情况下删除@Inject,则会收到

  

无法解析ComponentName的所有参数:(?)

答案 2 :(得分:3)

Angular中的IoC容器使用构造函数中的类型声明来确定要注入构造函数参数的对象。

在您的示例中,&#34; public data: any&#34;参数无法通过其类型声明确定,因为它被定义为&#34; any&#34;。为了解决这个问题,你必须使用&#34; @Inject(MAT_DIALOG_DATA)&#34;装饰器告知IoC容器必须注入的对象&#34; data&#34;参数。

同样在您的示例中,&#34; @Inject&#34;装饰器与InjectionToken一起使用,使事情变得更复杂:)

InjectionToken实际上是一个类,用于命名IoC容器用于注入其他类的对象。通常,您可以使用任何类名作为IoC注入的标记(例如&#34; MatDialogRef<DialogOverviewExampleDialog>&#34;在您的示例中),这样可以正常工作。但是当你开始编写你的UnitTests时,你意识到你需要使用Mock对象而不是真正的对象注入你的类,当你使用真正的类名作为你的标记时,你不能这样做。

要解决此问题,您可以使用Interfaces作为令牌名称,这实际上是正确的解决方案,但由于JavaScript不支持接口,因此您无法使用Interface名称作为令牌,因为已编译的代码确实存在不包含Interface个定义。

由于这一切,您需要使用InjectionTokenInjectionToken允许您将任何对象注入构造函数。您只需要在模块中声明它并映射到要注入的真实类。这样,您可以为生产和测试代码使用不同的类。