Vue 3 核心教學:掌握 computed(計算屬性)的快取機制與效能優化
在開發前端網頁時,我們經常需要對原始資料進行加工處理後再渲染到畫面上。例如:將名與姓拼接成完整姓名、過濾並排序一整串商品清單、或是根據購物車內容計算總金額與折價券。
如果您直接在 HTML 模板裡寫複雜的 JavaScript 運算表達式,不僅會讓程式碼變得臃腫、難以維護,更會對網頁渲染效能造成嚴重的負擔。
在 Vue 3 中,處理 衍生資料 的最佳解決方案就是 computed。本文將帶您全面拆解 computed 的核心語法、直擊底層的快取優勢,並釐清實務上最常搞混的技術選型。
這讓計算屬性非常適合:
- 從多個資料組合出新的值,例如:
firstName + lastName → fullName。 - 對陣列做過濾或統計,例如:
todos.filter(t => t.done).length。 - 格式化顯示的數值,例如:匯率換算、日期格式化。
什麼是 computed?核心語法範例
computed 是一個接收 Getter 函數的響應式 API,它會根據其依賴的 響應式資料,例如:ref() 或 reactive() 進行計算,並回傳一個 唯讀(Read-only)的響應式引用物件。在 <script> 中存取時需要加上 .value,但在 <template> 中則會自動解包,直接使用即可。
const firstName = ref('John');
const lastName = ref('Doe');
// 宣告一個計算屬性 fullName
const fullName = computed(() => {
return `${firstName.value} ${lastName.value}`;
});<input v-model="firstName" placeholder="First Name" type="text">
<input v-model="lastName" placeholder="Last Name" type="text">
<p>完整姓名:{{ fullName }}</p>直擊底層:computed 的快取機制
新手常會問:直接寫一個普通的 method 函數來回傳結果也可以呈現畫面,為什麼一定要用 computed?
答案就在於:快取機制。
- method:只要網頁上的任何資料改變、觸發畫面重新渲染,method 就會被重新執行一次。即便它內部的資料根本沒有變,它依然會傻傻地重新運算。
- computed:它會自動記住上次算好的結果。只有當它內部綁定的變數,例如:上面的
firstName或lastName發生改變時,它才會重新計算。如果依賴變數沒有變,不論網頁重新渲染多少次,computed 都會立刻回傳上一次計算好的快取結果。
效能差異巨大的場景
假設您需要對一個擁有 10,000 筆資料的陣列進行複雜的關鍵字過濾。如果用 method,只要使用者在網頁其他地方點擊一個不相干的按鈕,這 10,000 筆資料就會被重新過濾一次,造成網頁延遲;而用 computed 則只會在關鍵字真正變更時才執行,大幅優化網頁效能!
實務進階:可寫的計算屬性
預設情況下,computed 是唯讀的。如果您嘗試直接修改它,例如:fullName.value = 'Alice Wang',Vue 會拋出警告。
但如果實務上真的需要修改 computed 的值,您可以傳入一個包含 get 和 set 的物件,打造可寫入的計算屬性:
const firstName = ref('John');
const lastName = ref('Wang');
const fullName = computed({
// 讀取時觸發
get() {
return `${firstName.value} ${lastName.value}`;
},
// 寫入(賦值)時觸發
set(newValue) {
const names = newValue.split(' ');
firstName.value = names[0] || '';
lastName.value = names[1] || '';
},
});
function updateName() {
// 當修改 fullName 時,set 函數會被觸發,進而自動反向更新 firstName 與 lastName
fullName.value = 'Wells Lee';
}快速比較 computed、method
| computed | method | |
|---|---|---|
| 快取機制 | 有 | 無 |
| 用途 | 同步組合、過濾或轉換現有資料 | 反應式事件處理 |
| 回傳 | 必須 | 可有可無 |
| 用法 | 多個變數影響出一個結果 | 觸發特定事件 |
總結:Computed 開發的三條金律
快速複習一下 Vue 3 computed 的實務秘訣:
- 只做純函數:computed 的 Getter 應該只專注於資料的計算與回傳。絕對不要在 computed 內部去修改其他狀態、觸發非同步請求或操作 DOM 節點,這些副作用請通通交給 watch 或 method。
- 避免直接修改計算屬性值:除非您明確配置了
set函數,否則,請將 computed 當作唯讀的衍生資料。 - 保持資料響應式:computed 內部必須存取 Vue 的響應式資料,例如:ref、reactive,其快取與觸發機制才能正確運作。
常見問題
computed 與 method 有什麼差別?
computed 有快取,只有依賴的響應式資料改變時才會重新計算;method 每次重新渲染都會被完整執行一次。顯示衍生資料用 computed,事件觸發的動作用 method。
computed 什麼時候會重新計算?
只有在它內部用到的響應式資料發生變化時。其他無關的狀態改變或畫面重繪都不會觸發重算,而是直接回傳上一次的快取結果。
computed 可以被賦值嗎?
預設是唯讀的,直接賦值會出現警告。若確實需要寫入,可以傳入包含 get 與 set 的物件,在 set 中反向更新來源資料。
computed 可以做非同步請求嗎?
不行。getter 應該是純函式,只做計算並回傳結果。API 請求、計時器、DOM 操作這類副作用請交給 watch 或 watchEffect。
computed 與 watch 該怎麼選?
要從既有資料算出一個新值拿去顯示,用 computed;資料改變後要去做一件事,例如:呼叫 API、寫入 localStorage,用 watch。
computed 在模板中需要加 .value 嗎?
不需要,模板會自動解包。但在 <script> 中存取 computed 的結果時,同樣要加上 .value。