computed 的由來
computed
的設計是為了不在模板中放入太多的運算。例如:
<div id="example">
{{ message.split('').reverse().join('') }}
</div>
每個值的運算方式都要這樣寫的話,會讓版面的可讀性降低。
computed 的使用方式
<div id="example">
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
reversedMessage: function () {
console.log('computed reversedMessage')
return this.message.split('').reverse().join('')
}
}
})
我們可以看到結果:
Original message: "Hello"
Computed reversed message: "olleH"
computed
和data
屬性一樣能把值取出來放在樣板上使用。computed
在偵測到與之相關聯的原始資料有修改後,就會執行一次。
computed 特性
- 在生命週期 created 時,computed 會被建立和執行一次,之後如果與之相關聯的原始資料沒有更新,就不會重新求值,而是回傳暫存的值。
- computed 無法被其他方法修改。
- computed 必須回傳一個值( 要用 return )。
- computed 無法傳入參數。
computed 和 methods 差別
computed
只有在與之相關聯的原始資料發生改變時,才會重新求值。而method
在任一資料發生改變、或是被呼叫時便會執行。method
可傳入參數,且不一定要回傳一個值。
<div id="example">
<p>Irrelevant data: "{{ otherMessage }}"
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ computedReversedMsg }}"</p>
<p>Method reversed message: "{{ methodReversedMsg() }}"</p>
</div>
new Vue({
el: '#example',
data: {
message: 'Hello',
otherMessage: 'Hi'
},
computed: {
computedReversedMsg() {
console.log('computed reversedMessage')
return this.message.split('').reverse().join('')
}
},
methods:{
methodReversedMsg() {
console.log('method reversedMessage')
return this.message.split('').reverse().join('')
}
}
})
假設data
裡有兩個資料,一個和 computed 、 methods 都沒關係的otherMessage
,一個是會影響 computed 和 methods 的message
。
當我更改了otherMessage
時,因為沒有觸發 computed 內的原始資料,所以 computed 不會執行。但 methods 內卻因有資料變動,而執行了一遍。
computed 和 watch 差別
- watch 只會偵測單一值,當該值有變化時,就會執行。
- watch 可傳入參數,第一個參數是更新後的值,第二是舊值。
- watch 可以處理非同步工作。
<div id="example">
<p>firstName: "{{ firstName }}"</p>
<p>lastName: "{{ lastName }}"</p>
<p>fullName: "{{ fullName }}"</p>
</div>
new Vue({
el: '#example',
data: {
firstName: 'Chloe',
lastName: 'Lin',
fullName: 'Chloe Lin'
},
watch:{
firstName: function (val) {
console.log('watch firstName')
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
console.log('watch lastName')
this.fullName = this.firstName + ' ' + val
}
}
})
更改 firstName 時,由於 watch 監聽 firstName ,因此執行函式,進而修改 fullName 。
這種情況,使用 computed 看起來更簡潔,且有暫存資料,效能會比較好。
<div id="example">
<p>firstName: "{{ firstName }}"</p>
<p>lastName: "{{ lastName }}"</p>
<p>fullName: "{{ fullName }}"</p>
</div>
new Vue({
el: '#example',
data: {
firstName: 'Chloe',
lastName: 'Lin',
},
computed: {
fullName(){
return this.firstName + ' ' + this.lastName
}
}
})
getter 與 setter
一般情況下,computed只會調用 getter 。但在某些情況下你可以根據你的需求使用 setter 。例如在input
中,computed的資料綁定 v-model 。 input 中的值會以參數 newValue 傳進 computed 中的 setter 作處理,再拋給 getter ,最後輸出畫面。
<div id="example">
<input type="text" name="name" v-model="fullName">
<label for="">{{ fullName }}</label>
<p>firstName: {{ firstName }}</p>
<p>lastName: {{ lastName }}</p>
</div>
new Vue({
el: '#example',
data: {
firstName: 'Chloe',
lastName: 'Lin'
},
computed: {
fullName: {
// getter
get: function () {
return this.firstName + ' ' + this.lastName
},
// setter
set: function (newValue) {
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
},
})
參考資料
那些關於 Vue 的小細節 - Computed 中 getter 和 setter 觸發的時間點
不只懂 Vue 語法:試解釋 computed、watch 與 methods 的差異?
Computed Properties and Watchers