Angular框架专题

Angular框架中的Provider依赖注入(DI)

2021-12-13  本文已影响0人  听书先生

依赖注入是Angular的核心,在设计应用的时候会使用到,它可以帮助我们提高开发效率和模块化程度,DI是一种编码模式,其中的类会从外部源中请求获取依赖,而不需要我们去创建它们,Angular系统中通过在类上添加@Injectable装饰器来告诉系统这个类(服务)是可注入的。

1、使用Provider来描述与Token关联的依赖对象的创建方式

Angular中依赖对象的创建方式共用4种:

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的资料)

上一篇下一篇

猜你喜欢

热点阅读