javascript Angular 4:何时以及为什么在构造函数中使用@Inject?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/47050450/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Angular 4: When and why is @Inject is used in constructor?
提问by Vikas Bansal
Problem Statment
问题陈述
I am learning Angular 4 and I have stumble upon a code where @Injectis being used in a constructorand I am not able to figure out why...
我正在学习 Angular 4,我偶然发现了一个@Inject在 a 中使用的代码,constructor但我不知道为什么......
Code and Source
代码和来源
I am using Angular 4 Material
我正在使用 Angular 4 材质
Code Source:https://material.angular.io/components/dialog/overview
代码来源:https : //material.angular.io/components/dialog/overview
In the code, they are injecting MAT_DIALOG_DATA
在代码中,他们注入 MAT_DIALOG_DATA
constructor(public dialogRef: MatDialogRef<DialogOverviewExampleDialog>,
@Inject(MAT_DIALOG_DATA) public data: any
) { }
Can anyone please elaborate what does it mean and when/where should we do this?
任何人都可以详细说明这是什么意思以及我们应该在何时/何地执行此操作?
采纳答案by Rahul Singh
@Inject()is a manualmechanism for letting Angular know that a parametermust be injected.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) { } }In the above we've asked for
chatWidgetto be the singleton Angular associates with theclasssymbolChatWidgetby calling@Inject(ChatWidget). It's important to note that we're usingChatWidgetfor its typings andas a referenceto its singleton. We are notusingChatWidgetto instantiate anything, Angular does that for us behind the scenes
@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成为 Angular通过调用 与class符号关联的单例。重要的是要注意我们使用 它的类型和作为对它的单例的引用。我们没有使用实例化任何东西,Angular 在幕后为我们做这件事ChatWidget@Inject(ChatWidget)ChatWidgetChatWidget
From https://angular-2-training-book.rangle.io/handout/di/angular2/inject_and_injectable.html
来自https://angular-2-training-book.rangle.io/handout/di/angular2/inject_and_injectable.html
回答by eko
If MAT_DIALOG_DATAis a non-factory/class dependency (like stringfor your configs), you usually use @Inject.
如果MAT_DIALOG_DATA是非工厂/类依赖项(比如string你的配置),你通常使用@Inject.
Also check InjectionToken: https://angular.io/guide/dependency-injection#injectiontoken
还要检查InjectionToken:https: //angular.io/guide/dependency-injection#injectiontoken
One solution to choosing a provider token for non-class dependencies is to define and use an
InjectionToken
为非类依赖项选择提供者令牌的一种解决方案是定义和使用
InjectionToken
Here's a plunker: http://plnkr.co/edit/GAsVdGfeRpASiBEy66Pu?p=preview
这是一个plunker:http://plnkr.co/edit/GAsVdGfeRpASiBEy66Pu?p=preview
if you remove @Injectin these cases you will receive a
如果您@Inject在这些情况下移除,您将收到
Can't resolve all parameters for ComponentName: (?)
无法解析 ComponentName 的所有参数:(?)
回答by Yildiray Meric
IoC container in Angular uses the type declarations in the constructor to determine the objects to be injected to the constructor parameters.
Angular 中的 IoC 容器使用构造函数中的类型声明来确定要注入构造函数参数的对象。
In your example, "public data: any" parameter could not be determined by its type declaration because it's defined as "any". In order to solve this problem, you have to use "@Inject(MAT_DIALOG_DATA)" decorator to inform the IoC container about the object that must be injected to "data" parameter.
在您的示例中,“ public data: any” 参数无法由其类型声明确定,因为它被定义为“any”。为了解决这个问题,你必须使用“ @Inject(MAT_DIALOG_DATA)”装饰器来通知IoC容器必须注入“ data”参数的对象。
Also in your example, "@Inject" decorator is used with an InjectionTokento complicate things a little more :)
同样在您的示例中,“ @Inject” 装饰器与 anInjectionToken一起使用使事情变得更加复杂:)
An InjectionTokenis actually a class which is used to name the objects to be used by IoC container to inject in to other classes. Normally you could use any classes name as a token for IoC injection (like "MatDialogRef<DialogOverviewExampleDialog>" in your example) and this works fine. But when you start writing your UnitTests you realize that you need to use Mock objects instead of real objects to be injected into your classes and when you use real class names as your tokens, you could not do that.
AnInjectionToken实际上是一个类,用于命名 IoC 容器使用的对象以注入其他类。通常,您可以使用任何类名作为 IoC 注入的标记(例如MatDialogRef<DialogOverviewExampleDialog>您的示例中的“ ”),这很好用。但是当你开始编写你的单元测试时,你意识到你需要使用 Mock 对象而不是真实的对象来注入你的类,当你使用真实的类名作为你的标记时,你不能这样做。
To solve this problem you could use Interfacesas token names and this is actually the right solution, but since JavaScript does not support interfaces you could not use Interfacenames as tokens, because transpiled code does not contain Interfacedefinitions.
要解决这个问题,您可以将Interfaces名称用作标记名称,这实际上是正确的解决方案,但是由于 JavaScript 不支持接口,因此您不能将Interface名称用作标记,因为转换后的代码不包含Interface定义。
As a result of all this, you need to use InjectionToken. An InjectionTokenallows you to inject any object into your constructor. You just need to declare it in your modules and map to the real class that you want to be injected. This way you could use different classes for your production and test codes.
因此,您需要使用InjectionToken. AnInjectionToken允许您将任何对象注入到构造函数中。你只需要在你的模块中声明它并映射到你想要注入的真实类。这样你就可以为你的生产和测试代码使用不同的类。

