当前位置: 首页
前端开发
从源码角度深入解析Angular @Injectable注解的核心工作原理

从源码角度深入解析Angular @Injectable注解的核心工作原理

热心网友 时间:2026-06-17
转载

正文

首先,让我们观察两个来自 SAP 电商云 Spartacus UI 的 Angular 服务类。这两个类都添加了 @Injectable 装饰器,唯一的区别在于是否包含 providedIn 参数:

\

\

@Injectable() 装饰器

@Injectable() 装饰器的作用非常明确——它告诉 Angular:这个类可以被纳入依赖注入系统。换句话说,这是让服务具备“可注入”能力的关键入口。

如果加上 providedIn: 'root',就表示该服务在整个应用范围内都是可见的,任何组件或其他服务都可以直接请求它,而无需在模块中手动注册。

那么,当我们在组件中需要使用某个服务时,Angular 是如何知道要注入哪个实例的呢?答案隐藏在构造函数的参数类型里。来看一个典型例子:

import { Component } from '@angular/core';
import { Http } from '@angular/http';
@Component({
  selector: 'example-component',
  template: '

I am a component

' }) class ExampleComponent { constructor(private http: Http) { // use `this.http` which is the Http provider } }

这里 private http: Http 的类型是 Http(注意大写 H),Angular 会自动将它匹配到对应的服务实例。听起来很神奇?对于 JavaScript 开发者来说,这确实有点“黑魔法”的味道。

浏览器运行时,http 参数从哪来?

要知道,类型定义是 TypeScript 特有的特性,编译成 JavaScript 后按理说应该消失得无影无踪。那么浏览器中的 JavaScript 凭什么还能认出 http 参数该是什么?

秘密藏在 tsconfig.json 里的一个配置:emitDecoratorMetadata 设为 true。这个开关会把参数的类型信息作为元数据,嵌入到编译后的装饰器代码里。来看上面那段 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: '

I am a component

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

发现关键点了吗?__metadata('design:paramtypes', [Http]) 这一行把 Http 类型存储为元数据。因此 @Component 装饰器在运行时会被转换成普通的 ES5 函数,而 __decorate 负责把元数据打包在一起。Angular 拿到这个元数据后,就知道构造函数的第一参数应该注入 Http 令牌对应的实例,然后把它赋值给 this.http

function ExampleComponent(http) {
  this.http = http;
}

整个过程环环相扣:TypeScript 的类型信息通过 emitDecoratorMetadata 保留下来,装饰器元数据告诉 Angular 该注入什么,最终依赖注入系统优雅地完成了服务的装配。这就是 @Injectable 背后最核心的工作原理。

来源:https://www.jb51.net/javascript/288519s03.htm

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

同类文章
更多
HTML5视频播放器播放记录及断点续传实现

HTML5视频播放器播放记录及断点续传实现

HTML5视频播放器断点续传需手动实现:通过timeupdate事件每5-10秒保存播放进度至localStorage,配合visibilitychange和beforeunload确保离开时存盘;页面加载后从本地读取进度,在loadedmetadata事件中设置currentTime恢复;注意处理视频时长变化、跨设备限制及移动端暂停问题。

时间:2026-07-09 06:55
全面详解JavaScript String类型处理多语言字符的实现方法

全面详解JavaScript String类型处理多语言字符的实现方法

JavaScript的String类型底层采用UTF-16编码,处理中文、emoji等多语言字符时需注意代理对问题,不能直接用length或下标访问。推荐做法:用Array from或for of遍历真实字符,正则加u标志;截取用Array from() slice();大小写转换需指定locale参数;排序使用localeCompare实现本地化排序才

时间:2026-07-09 06:55
details标签在数据表格语义化中的正确应用

details标签在数据表格语义化中的正确应用

details标签语义上用于承载补充性说明,而非核心业务数据,不具备数据绑定、CRUD等操作能力,不能替代数据表格详细视图。在实际项目中应作为增强层使用,如折叠非必要信息,避免破坏主干结构。

时间:2026-07-09 06:55
手写递归遍历与标准查找的基准测试耗时对比

手写递归遍历与标准查找的基准测试耗时对比

评估手写递归原型遍历与标准查找的时间开销,关键在于引擎的内联缓存机制。通过构造原型链、控制变量并用Benchmark js测试,结合DevTools分析可知,影响性能的核心是引擎能否将属性访问编译为内存偏移指令,而非递归层数本身。

时间:2026-07-09 06:55
Vue.js响应式系统:单向数据流与数据劫持协同机制

Vue.js响应式系统:单向数据流与数据劫持协同机制

Vue响应式系统依靠单向数据流与数据劫持协同驱动视图更新。数据劫持拦截变量写入并触发依赖通知,事件系统负责采集用户操作,v-model仅为语法糖,本质是事件监听与手动赋值。单向流确保状态变更路径单一,提升可维护性。

时间:2026-07-09 06:55
热门专题
更多
刀塔传奇破解版无限钻石下载大全 刀塔传奇破解版无限钻石下载大全
洛克王国正式正版手游下载安装大全 洛克王国正式正版手游下载安装大全
思美人手游下载专区 思美人手游下载专区
好玩的阿拉德之怒游戏下载合集 好玩的阿拉德之怒游戏下载合集
不思议迷宫手游下载合集 不思议迷宫手游下载合集
百宝袋汉化组游戏最新合集 百宝袋汉化组游戏最新合集
jsk游戏合集30款游戏大全 jsk游戏合集30款游戏大全
宾果消消消原版下载大全 宾果消消消原版下载大全
  • 日榜
  • 周榜
  • 月榜