在前面篇章中,有介紹 input/output 與父子元件溝通的方式,但在實際應用中,會遇到需要多個元件共享資料或邏輯的情況,而一但需要跨越兩個元件以上,input/output 的方式就會變得複雜且難以維護,這時候就需要使用 Service 來解決這個問題。
在 Angular 中,Service是一個用於封裝業務邏輯、數據存取的類別,提供服務給一個或多個組件使用。
透過 Angular CLI,可以快速建立 Service,指令如下:
ng g service <service-name>
ng g s <service-name>
Service 需要標記為可注入,表示這個類別可以被注入到其他類別中使用,否則在其他元件會無法被注入。
@Injectable({ providedIn: 'root' })
export class TasksService {
private tasks: Task[] = [];
getTasks(): Task[] {
return this.tasks;
}
}
Angular 標記服務為可注入的三種方式
@Injectable() 裝飾器
providedIn
屬性(如 providedIn: 'root'
),表示在整個應用程式中都提供。@Injectable({ providedIn: 'root' })
export class TasksService { ... }
另外兩種方式較少使用,僅在特定情境下,適合想要控制服務的作用範圍時。
bootstrapApplication 中的 providers
bootstrapApplication(AppComponent, {
providers: [TasksService]
});
元件的 providers 屬性
@Component({
selector: 'app-task',
providers: [TasksService],
...
})
而目前在元件內注入 Service 有兩種方式:
inject
函式注入 (Angular 14+)使用類別的建構函式來注入 Service,是過往最常見的方式。
在建構函式的參數中指定所需的服務類型,當 Angular 建立這個元件時會把可用的服務實例傳入建構子,這是 Angular 的依賴注入機制在運作。
// 參數前沒有加修飾子,Angular 不會自動把它當成類別的屬性;也就是說,必須在 constructor 裡手動指派才能在其他方法中使用。
export class TaskComponent {
private tasksService: TasksService;
constructor(tasksService: TasksService) {
this.tasksService = tasksService;
}
}
}
在建構函式的參數中,加入 private
或 public
等修飾子,會自動把這個參數當成類別的屬性,這樣就可以在類別的其他方法中使用這個服務。
// 傳統較常見的寫法
export class TaskComponent {
constructor(private tasksService: TasksService) { }
}
inject
是 Angular 14 引入的一個新函式,可以在類別內直接使用,更加直觀,能夠一眼看出這個類別依賴了哪些服務。
export class TaskComponent {
private tasksService = inject(TasksService);
}
今日目標:以 Service 來管理待辦事項
透過 Service,可以讓多個元件共享邏輯與資料,減少重複程式碼,明天會介紹元件的生命週期。