填写这份《一分钟调查》,帮我们(开发组)做得更好!去填写Home

Angular 中的依赖注入

Dependency injection in Angular

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

Dependencies are services or objects that a class needs to perform its function. Dependency injection, or DI, is a design pattern in which a class requests dependencies from external sources rather than creating them.

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

Angular's DI framework provides dependencies to a class upon instantiation. You can use Angular DI to increase flexibility and modularity in your applications.

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

See the现场演练 / 下载范例for a working example containing the code snippets in this guide.

创建可注入服务

Creating an injectable service

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

To generate a new HeroService class in the src/app/heroes folder use the following Angular CLI command.

      
      ng generate service heroes/hero
    

下列命令会创建默认的 HeroService

This command creates the following default HeroService.

src/app/heroes/hero.service.ts (CLI-generated)
      
      import { Injectable } from '@angular/core';

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

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

The @Injectable() decorator specifies that Angular can use this class in the DI system. The metadata, providedIn: 'root', means that the HeroService is visible throughout the application.

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

Next, to get the hero mock data, add a getHeroes() method that returns the heroes from mock.heroes.ts.

src/app/heroes/hero.service.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; }
}
    

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

For clarity and maintainability, it is recommended that you define components and services in separate files.

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

If you do combine a component and service in the same file, it is important to define the service first, and then the component. If you define the component before the service, Angular returns a run-time null reference error.

注入服务

Injecting services

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

Injecting services results in making them visible to a component.

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

To inject a dependency in a component's constructor(), supply a constructor argument with the dependency type. The following example specifies the HeroService in the HeroListComponent constructor. The type of heroService is HeroService.

src/app/heroes/hero-list.component (constructor signature)
      
      constructor(heroService: HeroService)
    

有关更多信息,请参阅在模块中提供依赖分层注入器

For more information, see Providing dependencies in modules and Hierarchical injectors.

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

Using services in other services

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

When a service depends on another service, follow the same pattern as injecting into a component. In the following example HeroService depends on a Logger service to report its activities.

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

First, import the Logger service. Next, inject the Logger service in the HeroService constructor() by specifying private logger: Logger within the parentheses.

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

When you create a class whose constructor() has parameters, specify the type and metadata about those parameters so that Angular can inject the correct service.

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

Here, the constructor() specifies a type of Logger and stores the instance of Logger in a private field called logger.

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

The following code tabs feature the Logger service and two versions of HeroService. The first version of HeroService does not depend on the Logger service. The revised second version does depend on Logger service.

      
      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;
  }
}
    

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

In this example, the getHeroes() method uses the Logger service by logging a message when fetching heroes.

下一步是什么?

What's next