填寫這份《一分鐘調查》,幫我們(開發組)做得更好!去填寫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