学习目录
本文主要给大家介绍的是关于Angular 4依赖注入之Injectable装饰器的相关内容,分享出来供大家参考学习,下面来看看详细的介绍:
本系列教程的开发环境及开发语言:
- nofollow" target="_blank" href="https://www.typescriptlang.org/index.html">TypeScript
基础知识
装饰器是什么
装饰器的分类
- 类装饰器 (Class decorators)
- 属性装饰器 (Property decorators)
- 方法装饰器 (Method decorators)
- 参数装饰器 (Parameter decorators)
TypeScript 类装饰器
类装饰器声明:
类装饰器顾名思义,就是用来装饰类的。它接收一个参数:
target: TFunction - 被装饰的类
看完第一眼后,是不是感觉都不好了。没事,我们马上来个例子:
class Greeting {
constructor() { // 内部实现 }
}
let myGreeting = new Greeting();
myGreeting.greet(); // console output: 'Hello!';
@H_404_67@
上面的例子中,我们定义了 Greeter 类装饰器,同时我们使用了 @Greeter 语法,来使用装饰器。
Injectable 类装饰器使用
class HeroService {}
@H_404_67@
Injectable 装饰器
在介绍 Injectable 装饰器前,我们先来回顾一下 HeroComponent 组件:
constructor(private heroService: HeroService,private loggerService: LoggerService) { }
ngOnInit() {
this.loggerService.log('Fetching heros...');
this.heros = this.heroService.getHeros();
}
}
@H_404_67@
在 HeroComponent 组件的 ngOnInit 生命周期钩子中,我们在获取英雄信息前输出相应的调试信息。其实为了避免在每个应用的组件中都添加 log 语句,我们可以把 log 语句放在 getHeros() 方法内。
更新前 HeroService 服务
getHeros() {
return this.heros;
}
}
@H_404_67@
更新后 HeroService 服务
constructor(private loggerService: LoggerService) { }
heros: Array<{ id: number; name: string }> = [
{ id: 11,name: 'Magneta' }
];
getHeros() {
this.loggerService.log('Fetching heros...');
return this.heros;
}
}
@H_404_67@
当以上代码运行后会抛出以下异常信息:
上面异常信息说明无法解析 HeroService 的所有参数,而 HeroService 服务的构造函数如下:
该构造函数的输入参数是 loggerService 且它的类型是 LoggerService 。在继续深入研究之前,我们来看一下 HeroService 最终生成的 ES5 代码:
我们发现生成的 ES5 代码中,HeroService 构造函数中是没有包含任何类型信息的,因此 Angular Injector (注入器) 就无法正常工作了。那么要怎么保存 HeroService 类构造函数中参数的类型信息呢?相信你已经想到了答案 — 当然是使用 Injectable 装饰器咯。接下来我们更新一下 HeroService:
export class HeroService {
// ...
}
@H_404_67@
更新完上面的代码,成功保存后,在 http://localhost:4200/ 页面,你将看到熟悉的 "身影":
现在我们再来看一下 HeroService 类生成的 ES5 代码:
__decorate 函数
__Metadata 函数
我们发现相比未使用 Injectable 装饰器,HeroService 服务生成的 ES5 代码多出了 HeroService = __decorate(...)
这些代码。简单起见,我稍微介绍一下,通过 Injectable 装饰器,在编译时会把 HeroService 服务构造函数中参数的类型信息,通过 Reflect API 保存在 window['__core-js_shared__']
对象的内部属性中。当 Injector 创建 HeroService 对象时,会通过 Reflect API 去读取之前已保存的构造函数中参数的类型信息,进而正确的完成实例化操作。
我有话说
@Injectable() 是必须的么?
如果所创建的服务不依赖于其他对象,是可以不用使用 Injectable 类装饰器。但当该服务需要在构造函数中注入依赖对象,就需要使用 Injectable 装饰器。不过比较推荐的做法不管是否有依赖对象,在创建服务时都使用 Injectable 类装饰器。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者使用Angular 4能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对编程之家的支持。