阅读(1172) (9)

Angular 依赖注入

2022-06-28 10:46:06 更新

Angular 中的依赖注入

依赖项是指某个类执行其功能所需的服务或对象。依赖项注入(DI)是一种设计模式,在这种设计模式中,类会从外部源请求依赖项而不是创建它们。

Angular 的 DI 框架会在实例化某个类时为其提供依赖。可以使用 Angular DI 来提高应用程序的灵活性和模块化程度。

包含本指南中代码片段的可工作示例,请参见现场演练 / 下载范例

创建可注入服务

要想在 ​src/app/heroes​ 目录下生成一个新的 ​HeroService ​类,请使用下列 Angular CLI 命令。

ng generate service heroes/hero

下列命令会创建默认的 ​HeroService​。

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class HeroService {
  constructor() { }
}

@Injectable()​ 装饰器会指定 Angular 可以在 DI 体系中使用此类。元数据 ​providedIn: 'root'​ 表示 ​HeroService ​在整个应用程序中都是可见的。

接下来,要获取英雄的模拟数据,请添加一个 ​getHeroes()​ 方法,该方法会从 ​mock.heroes.ts​ 中返回英雄。

import { Injectable } from '@angular/core';
import { HEROES } from './mock-heroes';

@Injectable({
  // declares that this service should be created
  // by the root application injector.
  providedIn: 'root',
})
export class HeroService {
  getHeroes() { return HEROES; }
}

为了清晰和可维护性,建议你在单独的文件中定义组件和服务。

如果你确实要将组件和服务合并在同一个文件中,则必须先定义服务,再定义组件,这一点很重要。如果在服务之前定义组件,Angular 将返回运行时的空引用错误。

注入服务

注入某些服务会使它们对组件可见。

要将依赖项注入组件的 ​constructor()​ 中,请提供具有此依赖项类型的构造函数参数。下面的示例在 ​HeroListComponent ​的构造函数中指定了 ​HeroService​。​heroService ​的类型是 ​HeroService​。

constructor(heroService: HeroService)

在其他服务中使用这些服务

当某个服务依赖于另一个服务时,请遵循与注入组件相同的模式。在这里,​HeroService ​要依靠 ​Logger ​服务来报告其活动。

首先,导入 ​Logger ​服务。接下来,通过在括号中指定 ​private logger: Logger​,来在 ​HeroService ​的 ​constructor()​ 中注入 ​Logger ​服务。

当创建一个其 ​constructor() ​带有参数的类时,请指定其类型和关于这些参数的元数据,以便 Angular 可以注入正确的服务。

在这里,​constructor()​ 指定了 ​Logger ​的类型,并把 ​Logger ​的实例存储在名叫 ​logger ​的私有字段中。

下列代码具有 ​Logger ​服务和两个版本的 ​HeroService​。​HeroService ​的第一个版本不依赖于 ​Logger ​服务。修改后的第二个版本依赖于 ​Logger ​服务。

  • src/app/heroes/hero.service (v2)
  • import { Injectable } from '@angular/core';
    import { HEROES } from './mock-heroes';
    import { Logger } from '../logger.service';
    
    @Injectable({
      providedIn: 'root',
    })
    export class HeroService {
    
      constructor(private logger: Logger) {  }
    
      getHeroes() {
        this.logger.log('Getting heroes ...');
        return HEROES;
      }
    }
  • src/app/heroes/hero.service (v1)
  • import { Injectable } from '@angular/core';
    import { HEROES } from './mock-heroes';
    
    @Injectable({
      providedIn: 'root',
    })
    export class HeroService {
      getHeroes() { return HEROES; }
    }
  • src/app/logger.service
  • import { Injectable } from '@angular/core';
    
    @Injectable({
      providedIn: 'root'
    })
    export class Logger {
      logs: string[] = []; // capture logs for testing
    
      log(message: string) {
        this.logs.push(message);
        console.log(message);
      }
    }

在这个例子中,​getHeroes()​ 方法通过在获取英雄时通过 ​Logger ​来记录一条消息。