Javascript 角度4:构造函数中何时以及为什么使用@Inject?

Javascript 角度4:构造函数中何时以及为什么使用@Inject?,javascript,angular,constructor,angular-material2,Javascript,Angular,Constructor,Angular Material2,问题陈述 我正在学习Angular 4,我偶然发现了一个代码,其中@Inject正在构造函数中使用,我不知道为什么 代码和源代码 我用的是角4材质 代码来源: 在代码中,他们正在注入MAT\u DIALOG\u数据 constructor(public dialogRef: MatDialogRef<DialogOverviewExampleDialog>, @Inject(MAT_DIALOG_DATA) public data: any

问题陈述

我正在学习Angular 4,我偶然发现了一个代码,其中
@Inject
正在
构造函数中使用,我不知道为什么

代码和源代码

我用的是角4材质

代码来源:

在代码中,他们正在注入
MAT\u DIALOG\u数据

constructor(public dialogRef: MatDialogRef<DialogOverviewExampleDialog>,
             @Inject(MAT_DIALOG_DATA) public data: any
           ) { }
构造函数(public dialogRef:MatDialogRef,
@注入(MAT_对话框_数据)公共数据:任意
) { }
请任何人详细说明这意味着什么以及我们应该在何时/何地这样做

@Inject()
是一种手动机制,用于让Angular知道 参数必须被注入

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
作为单例 通过调用
@Inject(ChatWidget)
。需要注意的是,我们正在使用
ChatWidget
用于输入和引用其单例。 我们没有使用
ChatWidget
来实例化任何东西,Angular是这样做的 这对我们来说是幕后的


从中,如果
MAT\u DIALOG\u DATA
是非工厂/类依赖项(如
string
用于配置),则通常使用
@Inject

同时检查
InjectionToken

为非类依赖项选择提供者令牌的一个解决方案是定义并使用
InjectionToken


这里有一个小插曲:

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

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


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

在您的示例中,“
公共数据:any
”参数的类型声明无法确定,因为它被定义为“any”。为了解决这个问题,您必须使用“
@Inject(MAT\u DIALOG\u DATA)
”装饰器通知IoC容器必须注入到“
DATA
”参数的对象

同样在您的示例中,“
@Inject
”decorator与
InjectionToken一起使用,使事情变得更复杂:)

InjectionToken
实际上是一个类,用于命名IoC容器用于注入到其他类中的对象。通常,您可以使用任何类名称作为IoC注入的标记(如示例中的“
MatDialogRef
”),这很好。但是,当您开始编写单元测试时,您意识到需要使用模拟对象而不是真实对象来注入到类中,而当您使用真实的类名作为标记时,您无法做到这一点

要解决这个问题,您可以使用
接口
作为令牌名称,这实际上是正确的解决方案,但由于JavaScript不支持接口,您不能使用
接口
名称作为令牌,因为传输的代码不包含
接口
定义


因此,您需要使用
InjectionToken
InjectionToken
允许您将任何对象注入构造函数。您只需要在模块中声明它,并映射到要注入的实际类。通过这种方式,您可以为生产代码和测试代码使用不同的类。

注入
ChatWidget
组件,使
组件的行为类似于
单例服务
,以便组件状态在整个应用程序中保持不变。是动机吗?我明白了吗?@VikasBansal Rahul是对的,但这里不是这样,即使这里没有使用
@Inject
,并且服务是在根级别提供的,服务仍然是单例的。如果你阅读了这个答案中链接下方的段落,你会发现它没有什么区别。不是组件,而是利用组件中的
单例服务
。如果将其放置在根级别,它将在整个应用程序中表现为单例,否则仅在组件级别上。我认为它不会向下延伸到子组件。AngularJS中的componentoC容器是单例的,我想这只是注入令牌的用例之一,您也可以使用注入令牌将参数传递给您的服务谢谢您的回答,示例plunker非常有用!我想知道为什么我们要使用
InjectionToken
而不是我们可以从另一个共享文件中要求的简单常量?或者甚至可能只是组件上定义的变量?@philipyoo 1原因可能是您可能希望替换使用注入令牌的服务。另一种是模块化方法;您可以通过.forRoot()传递config选项,并通过Inject在类中使用它们