網頁製作完成,在檢查的時候卻發現有錯的表格內容,而同樣的表格內容卻在多個頁面出現,要改就要重工五次,這就是我時常碰到的問題。不僅浪費時間難維護,也有可能手誤其中一頁沒有改好,這時有了methods和computed可以一次改也降低改錯的機會。
在不認識methods之前會在{{...}}
裡面寫{{price*quantity}}
,知道有methods用法後會將重複的部分取出來包在函式中,之後要使用只需要寫{{subTotal()}}
就可以叫出一樣的數值。
<p>金額共{{subTotal()}}元</p>
<!-- 中間略... -->
<p>金額共{{subTotal()}}元</p>
<!-- 中間略... -->
<p>金額共{{subTotal()}}元</p>
const vm = Vue.createApp({
data() {
return {
price: '100',
quantity: '10'
}
},
methods: {
subTotal: function () {
return this.price * this.quantity
}
}
}).mount('#app')
補充:
this.price
和this.quantity
中的this
指的是跟他包一起的data內數值
若是在methods使用箭頭函式會怎麼樣呢?
methods: {
subTotal: () => {
return this.price * this.quantity
}
}
此時的this
會變成window,所以畫面就會出現
一般函式在建立時是在 window 下,所以在 window 下使用箭頭函式自然會指向 window,要確實將箭頭函式宣告在物件內部,這樣 this
才會指向該物件。— 擷取自 卡斯伯's Blog
寫法跟methods差不多
//省
methods: {
subTotal: () => {
return this.price * this.quantity
}
},
computed: {
subTotal: function () {
return this.price * this.quantity
}
}
//省
差異處在於HTML模板中少了()
<p>金額共{{subTotal}}元</p>
這是不是代表著他們兩個是可以互相通用的呢?
接著來做個測試....
const vm = Vue.createApp({
data() {
return {
price: '100',
quantity: '10'
}
},
methods: {
subTotalMethods: function () {
console.log('methods')
return this.price * this.quantity
}
},
computed: {
computedComputed: function () {
console.log('subTotal')
return this.price * this.quantity
}
}
}).mount('#app');
<p>金額共{{subTotalMethods()}}元</p>
<p>金額共{{computedComputed}}元</p>
methods
subTotal
結果答案都是100*10,也就是1000,且console中都各執行一次。從這個角度來看似乎兩者並沒有差異。
<p>金額共{{subTotalMethods()}}元</p>
<p>金額共{{subTotalMethods()}}元</p>
<p>金額共{{subTotalMethods()}}元</p>
<p>金額共{{computedComputed}}元</p>
<p>金額共{{computedComputed}}元</p>
<p>金額共{{computedComputed}}元</p>
得到的結果
methods
methods
methods
subTotal
subTotalMethods()
出現幾次就會執行幾次。而computedComputed
只會執行一次,會有這樣的結果是因為
舉書本上的貨幣範例:
methods
<div id="app">
<p>日幣 = 0.278 台幣</p>
<div>台幣 <input type="text" v-model="twd" v-on:input="twd2jpy"></div>
<div>日幣 <input type="text" v-model="jpy" v-on:input="jpy2twd"></div>
<div>
//v-model是將input資料與data內的資料做綁定
//v-on是監聽作用,觸發事件後會執行方法
const vm = Vue.createApp({
data() {
return {
twd: 0.278,
jpy: 1
}
},
methods: {
twd2jpy: function () {
this.jpy = Number.parseFloat(Number(this.twd) / 0.278).toFixed(3)
},
jpy2twd: function () {
this.twd = Number.parseFloat(Number(this.jpy) * 0.278).toFixed(3)
}
},
}).mount('#app');
個幣當輸入事件v-on:input
被觸發時,就會去執行各自綁定的function,每執行一次methods就會跑一次。
computed
<div id="app">
<p>日幣 = 0.278 台幣,且 1 美金 = 28.540 台幣:</p>
<div>台幣 <input type="text" v-model="twd"></div>
<div>日幣 <input type="text" v-model="jpy"></div>
<div>美金 <input type="text" v-model="usd"></div>
</div>
const vm = Vue.createApp({
data() {
return {
twd: 1000,
}
},
computed: {
jpy: {
get() {
return Number.parseFloat(Number(this.twd) / 0.278).toFixed(3)
},
set(val) {
this.twd = Number.parseFloat(Number(val) * 0.278).toFixed(3)
}
},
usd: {
get() {
return Number.parseFloat(Number(this.twd) / 28.540).toFixed(3)
},
set(val) {
this.twd = Number.parseFloat(Number(val) * 28.540).toFixed(3)
}
}
}
}).mount('#app');
在HTML模板上面看到了v-model="jpy"
,但data
裡面卻只有twd的資料卻沒有jpy,也就是說computed可以產生data資料,jyp的資料透過computed對twd加工計算,在jpy更新的時候透過set()改寫twd的內容。
若有效能上的考量,建議採用 computed 的版本。最主要是 computed 有緩存資料的能力,因此會將「屬性計算後的結果暫存」。當資料修改時,computed 也會隨之修改,但這是針對於 data 有變化時。反之 methods 每次執行就會每次計算一次,在效能上考量就比較差。
如果資料量大,computed 自然會比較慢,只要資料變動就會觸發,無形之中執行次數也會增加勒,因此在大量資料時,會建議透過 methods 減少不必要的運算。
卡斯伯's Blog — 鐵人賽:箭頭函式 (Arrow functions)
https://wcc723.github.io/javascript/2017/12/21/javascript-es6-arrow-function/
Vue 筆記 - Computed 的 get() 與 set()
https://hsuchihting.github.io/vue-js/20200917/2086781732/