Service & DI
Service
Service 允許你在應用程式中共享邏輯和資料。 放共用的邏輯跟資料,讓這些資料可以在不同的 component 中被使用。
基本的 Service 結構
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class TasksService {}
依賴注入階層
依賴解析順序: Component → ElementInjector → Application root EnvironmentInjector / ModuleInjector → Platform EnvironmentInjector → NullInjector (錯誤)
提供 Service 的方法
1. 透過 @Injectable 裝飾器(推薦)
@Injectable({
providedIn: 'root',
})
這種方式會讓 service 在整個應用程式中以單一實例存在,並且使用 Tree-shakable 的方式只在需要時才會被包含進最終的 bundle 中。
2. 在 main.ts 中提供
// 原本
bootstrapApplication(AppComponent).catch((err) => console.error(err));
// 改成
bootstrapApplication(AppComponent, { providers: [TasksService] }).catch((err) =>
console.error(err)
);
這個方法會讓 Angular 在最一開始初始化時就載入這個 service。如果所有服務都用這個方法註冊,可能會導致載入速度變慢。
3. 在 Component 中提供
@Component({
selector: 'app-tasks',
standalone: true,
templateUrl: './tasks.component.html',
imports: [NewTaskComponent, TasksListComponent],
providers: [TasksService],
})
export class TasksComponent {}
這個方法讓 service 只在這個 component 以及這個 component 的子元件中可用。 注意:這樣會創建不同的 service 實例,不同於 root 提供的單一實例。
依賴注入 (DI)
component、directive、service 可以請求他們所依賴的值(dependency),然後由 Angular 提供。 不需要自己建立 service 實例,而是從 Angular 請求。
bootstrapApplication(AppComponent, { providers: [TasksService] }).catch((err) =>
console.error(err)
);
實際上,Angular 會自動幫你將 TasksService 作為 Token:
export const TasksServiceToken = new InjectionToken<TasksService>('tasks-service-token');
bootstrapApplication(AppComponent, {
providers: [{ provide: TasksServiceToken, useClass: TasksService }]
}).catch((err) => console.error(err));
這樣可以改變 token 的名稱,但在其他地方要注入 service 時就要使用你新創建的 token 名稱:
constructor(@Inject(TasksServiceToken) private tasksService: TasksService) {}
自定義 Providers
也可以藉此自定義 providers,例如提供常數或配置:
export const TASK_STATUS_OPTIONS = new InjectionToken<TaskStatusOptions>(
'task-status-options'
);
export const TaskStatusOptions: TaskStatusOptions = [
{ value: 'open', taskStatus: 'OPEN', text: 'Open' },
{ value: 'in-progress', taskStatus: 'IN_PROGRESS', text: 'In-progress' },
{ value: 'done', taskStatus: 'DONE', text: 'Done' },
];
export const taskStatusOptionsProvider: Provider = {
provide: TASK_STATUS_OPTIONS,
useValue: TaskStatusOptions,
};
在 component 中使用 inject 函數注入:
// 在 component 類別內部
taskStatusOptions = inject(TASK_STATUS_OPTIONS);
Last updated