Angular @Injectable 注解的工作原理浅析

Jerry Wang 发表于 2022/12/09 09:49:44 2022/12/09
【摘要】 本质上,@Component 装饰器被转换为普通的 ES5,并且一些额外的元数据通过 __decorate 赋值提供。 这反过来告诉 Angular 查找 Http 令牌并将其作为第一个参数提供给组件的构造函数 - 将其分配给 this.http.

下面是 SAP 电商云 Spartacus UI 两个 Angular Service 类,都加上了 @Injectable 的注解,区别就在于是否具有输入参数 providedIn


@Injectable() 装饰器指定 Angular 可以在 DI 系统中使用这个类。 这个注解的输入元数据,providedIn: ‘root’,意味着被注解的 Angular service 类,在整个应用程序中都是可见的。

当将服务(提供者)注入到我们的组件/服务中时,通过构造函数中的类型定义来指定我们需要的提供者。下面是一个例子:

import { Component } from '@angular/core';
import { Http } from '@angular/http';

@Component({
  selector: 'example-component',
  template: '<div>I am a component</div>'
})
class ExampleComponent {
  constructor(private http: Http) {
    // use `this.http` which is the Http provider
  }
}

这里的类型定义是 Http(注意大写的 H),Angular 会自动将其分配给 http。

对于 JavaScript 开发人员来说,上面的工作方式或许有些神奇。类型定义是特定于 TypeScript 的,所以我们编译的 JavaScript 代码理论上应该不知道在浏览器中运行它时我们的 http 参数是什么。

在我们的 tsconfig.json 文件中,我们将 emitDecoratorMetadata 设置为 true。 这会将有关参数类型的元数据发送到我们编译的 JavaScript 输出中的装饰器中。

让我们看看上面列举的 TypeScript 代码,实际上被编译成什么(为了清楚起见,我保留了 ES6 导入):

import { Component } from '@angular/core';
import { Http } from '@angular/http';

var ExampleComponent = (function() {
  function ExampleComponent(http) {
    this.http = http;
  }
  return ExampleComponent;
})();
ExampleComponent = __decorate(
  [
    Component({
      selector: 'example-component',
      template: '<div>I am a component</div>',
    }),
    __metadata('design:paramtypes', [Http]),
  ],
  ExampleComponent
);

从这里,我们可以看到编译后的代码,知道 http 就是 @angular/http 提供的 Http 服务 - 它被添加为我们的类的装饰器:

__metadata('design:paramtypes', [Http]);

所以本质上,@Component 装饰器被转换为普通的 ES5,并且一些额外的元数据通过 __decorate 赋值提供。 这反过来告诉 Angular 查找 Http 令牌并将其作为第一个参数提供给组件的构造函数 - 将其分配给 this.http:

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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