问题陈述
我正在学习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
) { }
任何人都可以详细说明它的含义以及我们应该在何时/何地进行此操作?
答案 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
。
同时检查InjectionToken
:https://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
个定义。
由于这一切,您需要使用InjectionToken
。 InjectionToken
允许您将任何对象注入构造函数。您只需要在模块中声明它并映射到要注入的真实类。这样,您可以为生产和测试代码使用不同的类。