Angular框架中的Provider依赖注入(DI)
2021-12-13 本文已影响0人
听书先生
依赖注入是Angular的核心,在设计应用的时候会使用到,它可以帮助我们提高开发效率和模块化程度,DI是一种编码模式,其中的类会从外部源中请求获取依赖,而不需要我们去创建它们,Angular系统中通过在类上添加@Injectable
装饰器来告诉系统这个类(服务)是可注入的。
1、使用Provider来描述与Token关联的依赖对象的创建方式
Angular中依赖对象的创建方式共用4种:
- 1、useClass
- 2、useValue
- 3、useExisting
- 4、useFactory
1.1、useClass:
import {NgModule, APP_INITIALIZER, Injectable} from '@angular/core';
import {BrowserModule, HammerGestureConfig, HAMMER_GESTURE_CONFIG} from '@angular/platform-browser';
...
@Injectable()
export class ApiService {
constructor(
public http: Http
)
}
@NgModule({
declarations: [AppComponent],
entryComponents: [],
imports: [
BrowserModule,
....
],
providers: [
....
{ provide: RouteReuseStrategy, useClass: ApiService }
],
bootstrap: [AppComponent]
})
export class AppModule {
}
1.2、useValue:
{ provide: 'API_URL', useValue: 'http://api.com/v2' }
1.3、useExisting:
{ provide: 'ApiServiceAlias', useExisting: ApiService }
1.3、useFactory:
export function configFactory(config: AppConfig) {
return () => config.load();
}
@NgModule({
...
providers: [
{ provide: APP_INITIALIZER, useFactory: configFactory,
deps: [AppConfig], multi: true }
]
})
export class CoreModule { }
2、使用Provide
使用Provide需要首先创建Token,Token的作用是用来标识依赖对象,Token值可能是Type、InjectionToken类的实例或者字符串。推荐使用InjectionToken.
然后根据实际的需求选择依赖对象的创建方式,如:useClass、useValue、useExisting、useFactory等方式。
接着在NgModule或者是Component中去注册providers
最后使用构造注入的方式,注入与Token关联的依赖对象。
/**
* 封装Http服务,如在每个Http的请求头中添加token
*/
@Injectable()
export class ApiService {
constructor(
// 调用Http服务后,返回Observable对象
public http: Http) {
}
...
}
@NgModule({
...
providers: [
{ provide: ApiService, useClass: ApiService }
]
})
export class AppModule { }
组件页面中去调起:
export class HomePage {
constructor(
public apiService: ApiService // 使用构造注入的方式,注入ApiService的实例对象
) { }
ngOnInit(): void {
this.apiService.get(url)
.map(res => res.json()) // 返回的res对象是Response类型的实例
.subscribe(result => {
...
})
}
}
当DI系统解析Providers时,都会对提供的每个provider进行规范化处理,也就是转换成标准的形式。
function _normalizeProviders(providers: Provider[], res: Provider[]): Provider[] {
providers.forEach(b => {
if (b instanceof Type) { // 支持简洁的语法,转换为标准格式
res.push({provide: b, useClass: b});
} else if (b && typeof b == 'object' && (b as any).provide !== undefined) {
res.push(b as NormalizedProvider);
} else if (b instanceof Array) {
_normalizeProviders(b, res); // 如果是数组,进行递归处理
} else {
throw invalidProviderError(b);
}
});
return res;
}
(参考了网上一些angular的资料)