前言
服务是NG的另一个核心部分,它充当了前端MV*结构中的M,它能够给其它构建块提供全局支持,并且使用依赖注入的方式进行工作。
依赖注入
这个概念借鉴于后端Java的Spring框架,只为解决一个全局共享对象的问题:项目中往往需要一个全局对象,总不能要一个new一个吧,如果需要的时候直接用同一个不方便多了?
为了解决这个全局共享对象的问题,依赖注入的思想提供了很好的解决方案。其实它就是单例模式。
- 组件级依赖注入
每个组件或指令可以有自己的提供者,称为本地提供者。如果没有,就沿着组件树向上查找。 - 模块级依赖注入
当一个组件申请获得一个依赖时,Angular 先尝试用该组件自己的注入器来满足它。如果没有组件级的依赖注入,就会冒泡至上层模块,甚至到根模块查找提供者来使用。
使用
- 使用@Injectable声明一个服务
@Injectable()
export class myService {
...
}
- 在Ng模块里的providers数组里注册这个服务
providers: [myService]
- 使用者类使用构造函数参数声明对服务的依赖
constructor(private mySvc: myService) {
...
}
提供商分类
要使用服务,首先要在模块里声明提供商。如果有更加定制化的需求,需要引入令牌。
- OpaqueToken(令牌)
令牌用来标识依赖项和提供者。是一种解决应用不同部分,可能使用相同的令牌来标识不同的服务的方案。
export const MY_SERVICE = new OpaqueToken("logger");
providers: [{ provide: MY_SERVICE, useClass: MyService }]
constructor( @Inject(MY_SERVICE) private mySvc: MyService) { }
- useClass
使用类指定服务,全局共享一个对象
providers: [{ provide: MyService, useClass: MyService }]
- useValue
使用对象指定服务,这时候不再共享同一个对象,而是单独实例化一个提供商
let my = new MyService();
providers: [{ provide: MyService, useValue: my}]
- useFactory
使用一个函数指定一个服务,在单独实例化一个提供商的基础上再自定义一些信息
providers: [{
provide: MyService, useFactory: () => {
let my= new MyService();
my.level = 2;
return my;
}
}]
- useExisting
使用另一个服务指定一个服务,相当于是别名。
providers: [MyService,{ provide: otherService, useExisting: MyService }]
- 其他配置参数
provide、multi、deps(将被解析和传递的一个提供者标记数组)、useFactory(创建服务对象的函数)
总结
NG的服务把传统前端开发中的和数据有关的部分抽离出来,成为一个单例供全局使用,解决了前端开发中管理数据流的痛点。