Angular 为什么要引入 injection token 的概念

举报
Jerry Wang 发表于 2022/08/27 22:44:25 2022/08/27
【摘要】 你可以定义和使用一个 InjectionToken 对象来为非类的依赖选择一个提供者令牌。这里的重点是:非类。下列例子定义了一个类型为 InjectionToken 的 APP_CONFIG .import { InjectionToken } from '@angular/core';export const APP_CONFIG = new InjectionToken<AppConfi...

你可以定义和使用一个 InjectionToken 对象来为非类的依赖选择一个提供者令牌。

这里的重点是:非类。

下列例子定义了一个类型为 InjectionToken 的 APP_CONFIG .

import { InjectionToken } from '@angular/core';

export const APP_CONFIG = new InjectionToken<AppConfig>('app.config');

这里的 APP_CONFIG 只是一个令牌 token,或者说是一个 place holder.

可选的参数 <AppConfig> 和令牌描述 app.config 指明了此令牌的用途。
接着,用 APP_CONFIG 这个 InjectionToken 对象在组件中注册依赖提供者。

providers: [{ provide: APP_CONFIG, useValue: HERO_DI_CONFIG }]

语义是,消费者代码里,注入 APP_CONFIG 的令牌,则运行时,令牌会被实际的值 HERO_DI_CONFIG 取代。这个 HERO_DI_CONFIG 不是一个 Angular class, 所以只能以 injection token 的方式注册提供者。

现在,借助参数装饰器 @Inject(),你可以把这个配置对象注入到构造函数中。

constructor(@Inject(APP_CONFIG) config: AppConfig) {
  this.title = config.title;
}

接口和依赖注入

虽然 TypeScript 的 AppConfig 接口可以在类中提供类型支持,但它在依赖注入时却没有任何作用。在 TypeScript 中,接口是一项设计期工件,它没有可供 DI 框架使用的运行时表示形式或令牌。

当转译器把 TypeScript 转换成 JavaScript 时,接口就会消失,因为 JavaScript 没有接口。

由于 Angular 在运行期没有接口,所以该接口不能作为令牌,也不能注入它。

因此,下列的代码是不合法的:

// Can't use interface as provider token
[{ provide: AppConfig, useValue: HERO_DI_CONFIG })]

我们不能把 interface 本身作为一个令牌,因此 Angular 引入了 injection token 的概念。

同样,下列的代码亦不合法,因为 interface 不能作为构造函数的输入参数类型注入。因此我们需要 @Inject, 将 interface 包裹一层之后再传入构造函数。

// Can't inject using the interface as the parameter type
constructor(private config: AppConfig){ }
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。