【问题标题】:How Angular manages non-Angular instancesAngular 如何管理非 Angular 实例
【发布时间】:2019-07-07 09:48:38
【问题描述】:

我有一个问题,当我们尝试将非 Angular “事物”注入组件时,Angular 如何管理它们的注入。

特别是,让我们举个例子,为 Angular 使用 ngx-modialog 库 (https://github.com/shlomiassaf/ngx-modialog)(我使用的是版本 6)

如果我遵循库的 Quikcstart 指南,这一切都很简单。但是,请注意这部分:

constructor(public modal: Modal) { } 
  • 那么,我的问题是Modal 实例是如何注入到我们的 AppComponent 构造函数中的?

    或者,一个更通用的问题是,Angular 如何“提供”这些非服务类/函数的实例?

  • 我的第二个问题是,这些“原型”类型的注入(我们尝试注入的新组件的新实例?)

感谢您的帮助。

【问题讨论】:

标签: angular dependency-injection


【解决方案1】:

我有一个问题,当我们尝试将非 Angular “事物”注入组件时,Angular 如何管理它们的注入。

所有可注入的东西在Angular中都被称为provider。每个提供者都以信息的形式呈现。

  • 提供者的标识
  • 提供者的价值是什么

Angular 需要首先确定一个提供者,然后它需要给出标识符是满足===表达式的JavaScript值,是任何JavaScript类型(即对象、数组、字符串、数字、函数)。

我们可以使用类构造函数作为标识符,因为它满足=== 表达式。

例如;

class MyService {}
// assume MyService is provided via a NgModule somewhere
const x: Type<MyService> = MyService;
console.log(x === MyService); // prints true
console.log(injector.get(x)); // prints MyService instance
console.log(injector.get(MyService)); // prints same MyService instance as above

当我们提供一个类构造函数作为提供者的标识符时,它被称为服务。使用依赖注入的类是最常见的做法,我们称它们为服务是因为它更容易理解。

那么,我的问题是 Modal 实例是如何注入到我们的 AppComponent 构造函数中的?

它之所以有效,是因为您在类的顶部添加了一个 @Component({...}) 装饰器。

TypeScript 将在首次声明类原型时调用类装饰器。装饰器是一个 JavaScript 函数,它接收原型作为参数。 Angular 在这个阶段检查具有构造函数的原型。使用对构造函数的引用 Angular 可以查看有多少参数及其类型。

请记住上面我展示了如何使用类构造函数从注入器中获取实例。 @Component() 装饰器对构造函数执行相同的操作以获取 modal 的实例。它修改原始构造函数,获取可注入值并将值作为参数传递。这一切都是可能的,因为我们在创建 Angular 项目时默认启用了 TypeScript 中的特殊功能。

或者,一个更通用的问题是,Angular 如何“提供”这些非服务类/函数的实例?

Angular 中有不同类型的提供者。有些是静态值,有些是工厂函数,还有类提供者。如果Modal 类型是一个类提供者,那么Angular 将在第一次它被注​​入时创建一个新实例。然后,该值会被 injector 实例缓存并重新使用。

我的第二个问题是,这些“原型”类型的注入(我们尝试注入的新组件的新实例?)

Angular 创建了一个注入器的。当一个 provider 被获取时,注入器搜索 tree 直到找到该 provider 的注入器。根据提供者的类型(见上文),会读取一个 value。如果是类类型,则该注入器会创建并缓存一个新实例。

如果没有提供该类型的注入器,则会引发类型未知的注入错误。

Modal 是从哪里来的?

Modal 是一个abstract 类,但它们仍然有一个唯一 构造函数,可以用作标识符提供者。

您正在使用的库具有为Modal 类提供功能的插件。例如; bootstrap 插件有一个为Modal 类声明provider 的模块。您可以在源代码中看到,他们使用自定义类提供程序将默认类替换为 不同 类。

https://github.com/shlomiassaf/ngx-modialog/blob/44f16f73a5418ac3c41f4ebbc3ed58538a1adea5/projects/plugins/bootstrap/src/lib/bootstrap.module.ts#L17

【讨论】:

  • 感谢您的解释。我确实需要更仔细地重新阅读文档。我读过的一些教程只关注“服务”,所以他们误导我们只考虑服务。
  • @ramcrys 不客气。如果您觉得这篇文章有用,请点赞。
猜你喜欢
  • 2021-09-12
  • 2022-06-15
  • 2018-07-31
  • 2018-04-28
  • 2019-06-10
  • 2021-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多