前言
呈上篇,在掌握如何使用服務元件並且透過 DI 將其注入元件中使用後,緊接著我們就可以利用此技巧將原本元件內的邏輯抽出進行重構了。
判斷服務元件的範圍
在這個例子中 Data Service 只會用在 ArticleModule ,所以最好是把 data.service 的兩隻檔案都搬進去模組資料夾內,比較方便管理。
但是現在的情況下並不能直接移動,因為這個服務很可能在不同地方被引用了,一旦移動位置就必須跟著改其他地方。
做法有二:
- 在建立服務元件時就必須確定這個服務元件要被放在哪個模組下,這樣就 OK 了
- 或者使用 Move TS 這個 VS Code 上的插件,協助移動 TS 檔案
現在這個情況就使用 Move TS 來處理吧!
如果已經裝好了這個插件,那麼在移動 TS 檔案的時候,這個插件就會自動地幫我們把所有參考到這個檔案的 TypeScript 檔一併修改路徑,讓我們測試看看。
- 對著要移動的檔案點右鍵,使用 Move TS 來搬運檔案
搬運並重構程式碼
接著開始搬運 ArticleList 的部分程式碼包含資料與邏輯的部分,都搬進 Data Service 。
Data Service
- 把 doDelete() 、 doChange() 搬出去
- 但搬運到服務元件內之後,此時方法的命名就沒這麼好了,因此也需要調整
- 搬運文章的資料並建立屬性
articleData
1 | import { Injectable } from '@angular/core'; |
這樣 Data Service 的部分算是處理好了,接下來回到 ArticleList 。
ArticleList
- 由於我們先前在測試時已經時做了相依注入
- 所以在建構式執行完之後會得到一個 Data Service 物件的實體
- 而且存在
datasvc
這個屬性裡面,因此可以從這取得原本文章的資料維持畫面的呈現。
- 而且存在
- 所以在建構式執行完之後會得到一個 Data Service 物件的實體
1 | import { Component, OnInit } from '@angular/core'; |
程式碼都搬運了,自然 Template 的部分也需要做調整:
- 因為 doDelete() 以及 doModify() 已經被轉移到 Data Service ,所以必須做調整
- 使用
datasvc
屬性即可取用服務元件下的方法- 特別注意如果前面冠有
private
是無法在 Template 內取用的,要改成public
- 因此將其修正為
public
- 因此將其修正為
- 特別注意如果前面冠有
- 使用
修正後即可順利取用方法
1 | <!-- Article START--> |
測試運行
迫不及待地馬上測試看看!
然後會發現完全沒有效果。
為什麼?明明 console.log 也沒有錯誤訊息?
問題在於,在 JavaScript 中有個非常重要的語言特性是:
- 所有的屬性、變數物件參考到的永遠是物件的本身
什麼意思呢? 先來看看服務元件內 doModify() 的寫法
1 | doModify(post: any){ |
意思是 this.atticleData
透過 map() 被賦值一個全新的物件
- 所以每一次進行 doModify() 時所得到的
atticleData
值都是一個全新的物件
但是第一次進行相依注入時, ArticleList 元件內的 ngOnInit() 我們是這麼寫的:
1 | ngOnInit() { |
就是把
this.datasvc.atticleData
所指向的物件參考傳給了atticleData
這個屬性
所以當服務元件 DataService 內重新又建立一個元件時,這裡的 ngOnInit() 可不會重新又執行一次,也就是說我們在 DataService 上做的任何修改 ArticleList 完全看不到。
如何修改
既然方法可以直接從服務元件內取用,那麼資料想必也是可以的。
所以我們修改 ArticleList 的 Template
1 | <!-- Article START--> |
因為改用 datasvc.atticleData
所以可以刪除 class 內不再用到的 atticleData
屬性
- 因為資料的來源就是由服務元件提供,自然就不需要寫
this.atticleData = this.datasvc.atticleData;
1 | import { Component, OnInit } from '@angular/core'; |
於是現在這個 ArticleList 元件的 class 基本上快被搬光了,只剩下一個服務元件 Data Service 的注入,所有的邏輯都在服務元件上,而 Template 是直接取用服務元件上的資料以及邏輯。
再次進行測試
大功告成!
小結
實作完成後發現服務元件蠻吃 JavaScript 觀念,如果基礎沒有打穩,當發生這個 Bug 時肯定找不到問題,更別說這個問題連開發者工具都沒顯示錯誤,若基礎不穩肯定不知道發生什麼事了。