Vuejs
在模板中要對資料計算或是轉換時,computed
與 method
往往能替我們做到同樣的事情,例如今天需要組合 姓氏
與 名稱
成為 全名
,我可以選擇 computed
完成,同時 method
也可以替我完成同樣任務(由於模板對於 expression
的支持,使得 Function call
也可以寫在模板中。)
computed: {
name: {
get: function () {
return this.lastName + " " + this.firstName;
},
set: function (value) {
const name = value.split(" ");
this.lastName = name[0];
this.firstName = name[1];
}
}
}
methods: {
name: function () {
return this.lastName + " " + this.firstName;
}
}
由於兩者皆能幫我們達成需求,那麼何時該使用 computed
?何時又該使用 methods
就成了令人困惑的問題,不過兩者其實並不相同,自官方教學中的敘述我們可以得知兩者的差距:
Vuejs.org 2.x
官網明確地點出了兩者的差距:
計算屬性是基於它們的響應式依賴進行緩存的;相比之下,每當觸發重新渲染時,調用方法將總會再次執行函數。
簡單來說 computed
只會在其依賴的資料 改變
的時候 重新計算求值
,儘管在模板中多次調用 computed
、或是改變其他資料觸發畫面 重新渲染
這件事,只要 computed property
原始依賴響應的資料 沒有更動
,Vue
並不會重新求取 computed property
,而是訪問其 緩存結果
;另外,method
則是一旦觸發重新渲染便會重新執行函式。
下圖為範例,來實證 computed
於 在模板中多次調用相同
、發生重新渲染
時,只要響應資料沒有變動,便不會重新計算取值,而是調用緩存的這件事。
computed property
elapse
為計算2020/09/02
和2020/09/22
的差距日期。
const vm = new Vue({
el: ".app",
data: {
startDay: "2020/09/02",
endDay: "2020/09/22",
text: "恩~"
},
computed: {
elapse() {
console.log("我執行一次了,computed");
const startDayArgumment = this.startDay.split("/");
const endDayArgument = this.endDay.split("/");
const startTime = new Date(startDayArgumment);
const endTime = new Date(endDayArgument);
const oneDayMilliseconds = 1000 * 60 * 60 * 24;
const elapse =
(endTime.getTime() - startTime.getTime()) / oneDayMilliseconds;
return elapse;
}
}
});
依照剛才所說,computed
只會在其依賴的資料改變的時候 重新計算求值
,於是我們透過對 computed property
中添加 comsloe.log("我執行一次了,computed")
驗證該 computed
在以下兩點情境中是否會重新求值,一旦重新求值,我們可以自 console 面板中快速確認:
computed property
computed property
<main class="app">
<h1>{{ elapse }}</h1>
<h1>{{ elapse }}</h1>
<h1>{{ elapse }}</h1>
</main>
computed property
無重新求值計算如同上述所言,在 elapse
所依賴的 startDay
以及 endDay
沒有更動的情況下,Vue 會訪問先前 elapse
的緩存結果,而不會重新取值,所以 console 面板並沒有任何 我執行一次了,computed
的提醒。
data
,觸發畫面重新渲染這個時候要在 data
中添加 text
屬性,並且在模板中使用 text
,藉由稍後更改 text
觸發重新渲染 re-render
:
<main class="app">
<h1>{{ text + startDay +" 和 "+ endDay +" 差距 " + elapse() +" 天" }}</h1>
</main>
接著在 console 中輸入以下更動,觸發重新渲染
vm.text = 'change'
computed property
無重新求值計算如同上述所言,在 elapse
所依賴的 startDay
以及 endDay
沒有更動的情況下,Vue 會訪問先前 elapse
的緩存結果。
說明完 computed property
的特性,以下簡略 computed
適用的場合:
現有資料
中組合、轉換成 新資料
時看完了 computed
,來看看相同情境下,method
的行為吧!
const vm = new Vue({
el: ".app",
data: {
startDay: "2020/09/02",
endDay: "2020/09/22",
text: "恩~"
},
methods: {
elapse() {
console.log("我執行一次了,method");
const startDayArgumment = this.startDay.split("/");
const endDayArgument = this.endDay.split("/");
const startTime = new Date(startDayArgumment);
const endTime = new Date(endDayArgument);
const oneDayMilliseconds = 1000 * 60 * 60 * 24;
const elapse =
(endTime.getTime() - startTime.getTime()) / oneDayMilliseconds;
return elapse;
}
}
});
同樣確認以下兩項情境,由於 methods
一旦畫面 re-render
便會重新計算,所以下列結果都會看到 method
重新取值:
methods
methods
<main class="app">
<h1>{{ elapse() }}</h1>
<h1>{{ elapse() }}</h1>
<h1>{{ elapse() }}</h1>
</main>
可以看到 method
乖乖按照調用的次數調用了三次 XD。
data
,觸發畫面重新渲染這個時候同樣在 data
中添加 text
屬性,並且在模板中使用 text
,藉由稍後更改 text
觸發重新渲染 re-render
:
<main class="app">
<h1>{{ text + startDay +" 和 "+ endDay +" 差距 " + elapse() +" 天" }}</h1>
</main>
接著在 console 中輸入以下更動,觸發重新渲染
vm.text = 'change'
可以看到一旦 re-render
method
也重新調用。
看完以上的範例,來做個小總結,computed
優點在於由於 緩存
的特性,一旦使用的大量的計算,在既有響應依賴資料沒有更動的前提下,computed
不會重新計算求值,減少性能上的開銷,反之,若是有需要隨時更新、不希望緩存的情境,則可以使用 method
替代,不過目前使用上 method
更常作為事件的方法調用,感謝看到這裡的你,我們明天見~。
若是文中有任何錯誤、錯字、想討論的內容,歡迎各位大大不吝鞭笞指正、交流分享,筆者不慎感激 ✦ ✦ ✦
▶︎ 筆者 github:https://github.com/YUN-RU-TSENG
▶︎ 老王賣瓜之筆者另一篇鐵人:每天來點 CSS Specification
▶︎ 倘若不斷向深處扎根,似乎就能茁壯成長 - RM
computed
是前端造出來的欄位
英國麵包、德國麵包、法國麵包通通都有,就是沒有屬於日本麵包;既然這樣,今後只好自己創造
突然想到這句 XD