前言
到目前為止大部分的程式碼都放在 ArticleModule ,而這個 Module 內包含三個元件,其中 ArticleList 是父元件 ; ArticleHeader 與 ArticleBody 為子元件。大部分的程式邏輯與資料全部都放在 ArticleList 內,那麼我們要如何利用服務元件來協助處理這部分呢?
服務元件
服務元件是一個類別,而類別內只有兩種東西
- 屬性
- 方法
既然類別內只有這兩種東西,此時就可以想著該把什麼東西給獨立抽離使其變成服務元件。
以 ArticleList 元件為例
在設計元件的時候,通常會把相關的資料或邏輯放在同一的元件做管理。
而這個元件的 OnInit() 內放有文章的初始化資料內容,因此:
- 可以把這些資料與資料處理邏輯抽離,建立一個 Data Service 的服務元件
建立一個服務元件 - Data Service
建立的方式同樣透過 Angular CLI 指令,以下則一即可:
ng generate service 名稱
ng g s data 名稱
此時會發現專案內多了兩支檔案,單元測試檔及服務元件主要的程式碼。
data.service.ts
1 | import { Injectable } from '@angular/core'; |
這樣的程式碼結構是不是跟之前建立元件時看到的很相似呢?
註冊 Data Service
建立好 Data Service 後,接著還需要將其註冊進模組 (Module) 內才可以使用。
目前有兩個模組,分別是 AppModule 以及 ArticleModule
- 要選擇的是 ArticleModule ,因為我們是要幫這個模組建立服務元件
如果要將服務元件註冊進模組內,必須:
- 加入一個 providers 屬性,值為陣列型別
- 這樣就可以放入多個服務的提供者,如
providers: [DataService]
- 這樣就可以放入多個服務的提供者,如
article.module
1 | import { NgModule } from '@angular/core'; |
這樣子服務元件就註冊完成了!
而任何一種元件內都可以透過相依注入 (DI) ,把服務元件取出來使用。
測試 Data Service
目前 Data Service 的確沒有任何程式碼在裡面,但我們可以做個小測試驗證一下。
準備 Data Service 內的程式碼
1 | import { Injectable } from '@angular/core'; |
將服務注入到元件內
接著使用相依注入,注入到 ArticleList 內。
如何進行相依注入:
- 宣告一個
dService
屬性,並且利用 TypeScript 宣告型別為 DataService- 不一定會叫做 DataServie ,是根據剛才建立的服務名稱不同也會改變
- 在元件的 constructor () 內宣告一個參數
datasvc
,並且利用 TypeScript 宣告型別為 DataService- 當我們透過建構式成功注入時,將
dService
屬性值給定datasvc
參數
- 當我們透過建構式成功注入時,將
1 | import { Component, OnInit } from '@angular/core'; |
第一次做相依注入的同時 Angular 會自動的 new
出 DataService 的 class
,所以參數 datasvc
得到的其實是一個物件的實體。
而不管有幾個 Component 要注入相同的元件,在預設的情況下 Angular 只會
new
一次,也就是最終只會得到一個唯一的物件實體。
如此一來不管是在任何的 Component 內,只要是相同的服務元件,就可以確保得到的物件是唯一的,因此可以更輕易的在不同元件間共享一些必要的資料。
將服務注入到元件內 - 利用 TypeScript
透過 TypeScript 有效的簡化使用相依注入時的語法
- 在建構式傳入的參數前面加上
public
或private
- 加上之後 TypeScript 預設會在 ArticleList 這個元件的類別自動宣告一個 DataServie 型別的屬性
- 也就是說屬性不再需要自己額外宣告了,只需要宣告建構式內的參數即可。
- 也不再需要將注入成功的值賦予給屬性
修改如下:
1 | import { Component, OnInit } from '@angular/core'; |
修改後一行就搞定了~而且完全等價於剛剛三行的寫法。
所以未來再進行其他的相依注入時,只是要適當地在建構式參數前面加上 public
或 private
,後面再透過 TypeScript 的型別標註,就可以快速完成 DI 。
如何在元件內使用注入的服務元件
以 ngOnInit() 為例:
- 直接調用剛才傳入建構式的參數名 (此時是 DataService 物件),可以印出觀察
- 因為是物件,可以使用 . 運算子執行裡面的方法
1 | ngOnInit() { |
最後,看看結果是否如我們預期吧!
小結
本篇介紹了如何建立服務元件以及注入到其他元件內,下一篇我們要使用這個技巧替 ArticleList 進行重構。