對于任何復(fù)雜邏輯夷恍,你都應(yīng)當(dāng)使用計(jì)算屬性王财。
<div id="computed">
<p>原信息:{{message}}</p>
<p>計(jì)算后:{{reverseMessage}}</p>
</div>
var vm = new Vue({
el: '#computed',
data: {
message: 'hello!',
},
computed: {
reverseMessage(){
// this指向vm實(shí)例
return this.message.split('').reverse().join('');
}
},
});
console.log(vm.reverseMessage); //!olleh
vm.message = '你好!';
console.log(vm.reverseMessage); //!好你
你可以打開瀏覽器的控制臺,自行修改例子中的 vm气破。vm.reversedMessage 的值始終取決于 vm.message 的值。
你可以像綁定普通屬性一樣在模板中綁定計(jì)算屬性餐抢。Vue 知道 vm.reversedMessage 依賴于 vm.message现使,因此當(dāng) vm.message 發(fā)生改變時(shí),所有依賴 vm.reversedMessage 的綁定也會更新旷痕。而且最妙的是我們已經(jīng)以聲明的方式創(chuàng)建了這種依賴關(guān)系:計(jì)算屬性的 getter 函數(shù)是沒有副作用 (side effect) 的碳锈,這使它更易于測試和理解。
計(jì)算屬性緩存 vs 方法
你可能已經(jīng)注意到我們可以通過在表達(dá)式中調(diào)用方法來達(dá)到同樣的效果:
<p>Reversed message: "{{ reversedMessage() }}"</p>
// 在組件中
methods: {
reversedMessage: function () {
return this.message.split('').reverse().join('')
}
}
我們可以將同一函數(shù)定義為一個方法而不是一個計(jì)算屬性欺抗。兩種方式的最終結(jié)果確實(shí)是完全相同的售碳。然而,不同的是計(jì)算屬性是基于它們的響應(yīng)式依賴進(jìn)行緩存的绞呈。只在相關(guān)響應(yīng)式依賴發(fā)生改變時(shí)它們才會重新求值团滥。這就意味著只要 message 還沒有發(fā)生改變,多次訪問 reversedMessage 計(jì)算屬性會立即返回之前的計(jì)算結(jié)果报强,而不必再次執(zhí)行函數(shù)。
相比之下拱燃,每當(dāng)觸發(fā)重新渲染時(shí)秉溉,調(diào)用方法將總會再次執(zhí)行函數(shù)。
我們?yōu)槭裁葱枰彺妫考僭O(shè)我們有一個性能開銷比較大的計(jì)算屬性 A召嘶,它需要遍歷一個巨大的數(shù)組并做大量的計(jì)算父晶。然后我們可能有其他的計(jì)算屬性依賴于 A 。如果沒有緩存弄跌,我們將不可避免的多次執(zhí)行 A 的 getter甲喝!如果你不希望有緩存,請用方法來替代铛只。
計(jì)算屬性的 setter
計(jì)算屬性默認(rèn)只有 getter 埠胖,不過在需要時(shí)你也可以提供一個 setter :
<div id="demo">{{ fullName }}</div>
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
},
computed: {
fullName: {
// getter
get: function () {
return this.firstName + ' ' + this.lastName
},
// setter
set: function (newValue) {
var names = newValue.split(' '); //先將字符串轉(zhuǎn)換成數(shù)組
this.firstName = names[0];
this.lastName = names[names.length - 1];
}
}
}
})
現(xiàn)在控制臺再運(yùn)行 vm.fullName = 'John Doe' 時(shí),setter 會被調(diào)用淳玩,vm.firstName 和 vm.lastName 也會相應(yīng)地被更新直撤。