Angular 依赖注入
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;
}
}
import { Injectable } from '@angular/core';
import { HEROES } from './mock-heroes';
@Injectable({
providedIn: 'root',
})
export class HeroService {
getHeroes() { return HEROES; }
}
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
来记录一条消息。