依赖注入的层级等等请查看示意图
https://www.processon.com/view/618b434c1e0853689b033111?fromnew=1

依赖提供商

不同的类都可用于提供相同的服务。 比如,下面的代码告诉注入器,当组件使用 Logger 令牌请求日志对象时,给它返回一个 BetterLogger 实例。

[{ provide: Logger, useClass: BetterLogger }]

当用BetterLogger替代Logger后,此时BetterLogger在应用内会被实例化两次

[
BetterLogger,
{ provide: Logger, useClass: BetterLogger }
]

所以如果当你需要必须实例化一次BetterLogger的时候就用到了useExisting

[
BetterLogger,
{ provide: Logger, useExisting: BetterLogger }
]


值提供商

有时候你会希望注入字符串、函数或对象。通常会用来定义参数或者API请求地址等

export const HERO_DI_CONFIG: AppConfig = {
apiEndpoint: 'api.heroes.com',
title: 'Dependency Injection'
};

[{ provide: AppConfig, useValue: HERO_DI_CONFIG })]

这里需要注意的是,我们的令牌除了本身可以使用的值意外也可以使用字符串或者InjectionToken对象

  • 字符串
export const HERO_DI_CONFIG: AppConfig = {
apiEndpoint: 'api.heroes.com',
title: 'Dependency Injection'
};

[{ provide: 'APP_CONFIG', useValue: HERO_DI_CONFIG })]


constructor(@Inject('APP_CONFIG') GLOBAL_ENV){}
  • InjectionToken对象
import { InjectionToken } from '@angular/core';

export const APP_CONFIG = new InjectionToken<AppConfig>('app.config');


//config.ts
export const HERO_DI_CONFIG: AppConfig = {
apiEndpoint: 'api.heroes.com',
title: 'Dependency Injection'
};

[{ provide: APP_CONFIG, useValue: HERO_DI_CONFIG })]


constructor(@Inject(APP_CONFIG) GLOBAL_ENV){}

相比于官方提供的方法这里更简洁的方法可以使用字符串,这样不需要在使用是频繁的引入config.ts文件


工厂提供商

当需要动态创建依赖值时,比如需要从第三方库创建依赖时,你不能直接访问第三方库的实例,这时候就需要工厂提供商,比如当我们登录后可以拿到某个列表,不登录时会返回一个空列表

export class HeroService {

HEROES = [1, 2, 3, 4]

constructor(
private isAuthorized: boolean
) {
}

getHeroes() {
let HEROES = [];

if (this.isAuthorized) {
HEROES = this.HEROES
} else {
HEROES = [];
}

return HEROES;
}
}

这时你需要一个isAuthorized标志来控制,虽然HeroService不能直接访问UserService,但是工厂函数可以

let heroServiceFactory = (userService: UserService) => {
return new HeroService(userService.user.isAuthorized);
};

export let heroServiceProvider =
{
provide: HeroService,
useFactory: heroServiceFactory,
deps: [UserService]
};

组件中使用时

heroServiceProvider.useFactory(this.UserService).getHeroes()