欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Angular入门之依赖注入

程序员文章站 2024-03-22 23:35:28
...

是什么

依赖注入(dependency injection,DI)是这样一个系统,它让程序中的某部分可以访问其他部分,而且我们可以配置它们的访问方式。
简单来说,就是new好了依赖的对象注入进去,而不是在类中显式的new一个依赖的对象。依赖注入的可以是继承依赖类(即constructor参数)的任何类

基于控制反转(Ioc)的设计原则,减弱耦合性

Angular入门之依赖注入


怎么用

即如何给组件注入服务:

  1. 创建该服务的类,服务类上面这个@Injectable()装饰器

  2. 配置要注入的依赖,即提供者
    Angular 在启动过程中自动为我们创建一个应用级注入器,即隐式注入器。我们必须通过注册provider来配置注入器,这些provider为应用创建所需服务。
    或者在 NgModule 中注册provider,或者在应用组件中。使用Provider:[1]告诉Angular如何*根据指定的令牌创建对象***1的内容见下部分

    • NgModule 中的provider是被注册到根注入器。这意味着在 NgModule 中注册的provider可以被整个应用访问。
    • 在应用组件中注册的provider只在该组件及其子组件中可用。
  3. 在准备接收注入的部件上声明该依赖
    先导入该服务(import),然后在组件的构造函数中声明它。声明有两种方式:使用Inject注解的和不使用Inject注解的
    非 Type 类型的参数只能用 @Inject(Something) 的方式注入;Type 类型的参数两种方式都可以,比如

//非Type类型
constructor(@Inject(ApiService) private apiService){ }

//Type类型
constructor(private http: Http) { }      //推荐
constructor(@Inject(Http) private http) { }
constructor(@Inject(Http) private http: Http) { }

因为 Type 类型的对象,会被 TypeScript 编译器编译。即我们通过 class 关键字声明的服务,最终都会编译成 ES5 的函数对象


显示注入器

可以写使用显式注入器的代码,但却很少这样做

  injector = ReflectiveInjector.resolveAndCreate([Car, Engine, Tires]);
  let car = injector.get(Car);

provider配置

  1. 单例模式:服务的构造函数无参数,每次注入时返回同一个实例,1的内容:
    {provide:'令牌名',useClass:注入服务的类名}
    可简写为:注入服务的类名

  2. 工厂模式:调用构造函数时需要提供参数
    {provide: '令牌名',useFactory:函数}

  3. 值模式:当需要一个常量,而它会根据应用的其他部分甚至环境进行重定义时,这种方式非常有用
    {provide: '令牌名', useValue: 'someValue'}

  4. 别名模式
    {provide: '令牌名', useValue: '其他令牌名'}

四种接口的API如下:

export interface ClassProvider {
  // 用于设置与依赖对象关联的Token值,Token值可能是Type、InjectionToken、OpaqueToken的实例或字符串
  provide: any; 
  useClass: Type<any>;
  // 用于标识是否multiple providers,若是multiple类型,则返回与Token关联的依赖对象列表
  multi?: boolean; 
}

export interface FactoryProvider {
  // 用于设置与依赖对象关联的Token值,Token值可能是Type、InjectionToken、OpaqueToken的实例或字符串
  provide: any;
  // 设置用于创建对象的工厂函数
  useFactory: Function;
  // 依赖对象列表
  deps?: any[];
  // 用于标识是否multiple providers,若是multiple类型,则返回与Token关联的依赖对象列表
  multi?: boolean;
}

export interface ValueProvider {
  // 用于设置与依赖对象关联的Token值,Token值可能是Type、InjectionToken、OpaqueToken的实例或字符串
  provide: any;
  // 设置注入的对象
  useValue: any;
  // 用于标识是否multiple providers,若是multiple类型,则返回与Token关联的依赖对象列表
  multi?: boolean;
}

export interface ExistingProvider {
  // 用于设置与依赖对象关联的Token值,Token值可能是Type、InjectionToken、OpaqueToken的实例或字符串
  provide: any;
  // 设置注入的对象
  useExisting: any;
  // 用于标识是否multiple providers,若是multiple类型,则返回与Token关联的依赖对象列表
  multi?: boolean;
}

推荐从设计模式看依赖注入