Vue(二) 計算屬性
模板內的表示式常用於簡單的運算,當過長或邏輯複雜時,難以維護,計算屬性就是解決該問題的
什麼是計算屬性
表示式如果過長,或邏輯更為複雜,就會變得臃腫甚至難以維護,比如:
<div>
{{ text.split('.').reverse().join('.') }}
</div>
該表示式包含 3 個操作,並不是很清晰,可以用計算屬性進行改寫:
<div id="app"> {{ reverseText }} </div> <script> var app = new Vue({ el: '#app', data: { text: '123,456' }, computed: { reverseText: function () { //這裡的 this 是當前的 Vue 例項 return this.text.split(',').reverse().join(','); } } }) </script>
所有的計算屬性都以函式的形式寫在 Vue 例項內的 computed 選項內,最終返回計算結果。
計算屬性的用法
除了上例簡單的用法,計算屬性還可以依賴多個 Vue 例項的資料。只要其中任一資料變化,計算屬性就會重新執行,檢視也會更新。例如,下面的例項是在展示購物車內兩個包裹的總價。
<div id="app"> {{ prices }} </div> <script> var app = new Vue({ el: '#app', data: { package1: [ { name: 'iphone xs max', price: 9999, count: 2 }, { name: 'ipad pro', price: 6666, count: 2 } ], package2: [ { name: 'apple', price: 20, count: 20 }, { name: 'orange', price: 18, count: 20 } ] }, computed: { prices: function () { var prices = 0; for(var i = 0; i < this.package1.length; i++) { prices += this.package1[i].price * this.package1[i].count; } for(var i = 0; i < this.package2.length; i++) { prices += this.package2[i].price * this.package2[i].count; } return prices; } } }) </script>
當 package1 和 package2 中的商品有任何變化時,比如購買數量變化或增刪商品時,計算屬性 prices 就會自動更新,檢視中的 prices 也會自動變化。
geter 和 setter
每一個計算屬性都包含一個 getter 和一個 setter,上面的兩個例子都是計算屬性的預設用法,只是利用了 getter 來讀取,在你需要時,也可以提供一個 setter 函式,當手動修改計算屬性的值時就會觸發 setter 函式,執行一些自定義操作,例如:
<div id="app"> {{ fullName }} </div> <script> var app = new Vue({ el: '#app', data: { firstName: 'Jack', lastName: 'Green' }, 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]; } } } }) </script>
當在瀏覽器的控制檯執行 app.fullName = 'John Doe'; 時,setter 就會被呼叫,資料 firstName 和 lastName 都會相對更新,檢視也會更新。
絕大多數情況下,我們只會用預設的 getter 方法來讀取一個計算屬性,在業務中很少用到 setter,因此在宣告一個計算屬性時,直接使用預設的方法即可,不必將 getter 和 setter 都宣告。
計算屬性除了上述簡單的文字插值外,還經常用於動態地設定元素的樣式名稱 class 和內聯樣式 style。當使用元件時,計算屬性也常用於動態傳遞 props。
計算屬性還有兩個很實用的小技巧:一個計算屬性可以依賴其他的計算屬性;二是計算屬性不僅可以依賴當前 Vue 例項的資料,還可以依賴其他例項的資料。
計算屬性快取
在上一篇介紹指令和時間時,你可能發現呼叫 methods 裡的方法也可以與計算屬性起到同樣的作用,比如本章第一個示例可以用 methods 改寫為:
<div id="app">
{{ reverseText() }}
</div>
<script>
var app = new Vue({
<!-- 注意:這裡的 reverseText 是方法,所以要帶() -->
el: '#app',
data: {
text: '123,456'
},
methods: {
reverseText: function () {
//這裡的 this 是當前的 Vue 例項
return this.text.split(',').reverse().join(',');
}
}
})
</script>
沒有使用計算屬性,在 methods 裡定義了一個方法實現了相同的效果,甚至該方法還可以接受引數,使用起來更靈活。那為什麼還需要計算屬性呢?原因就是計算屬性是基於它的依賴快取的,一個計算屬性所依賴的的資料發生變化時,它才會重新取值,所以 text 只要不改變,計算屬性也就不更新,例如:
computed: {
now: function() {
return Date.now();
}
}
這裡的 Dtae.now() 不是響應式依賴,所以計算屬性 now 不會更新。但是 methods 則不同,只要重新渲染,它就會被呼叫,因此函式也會被執行。
使用計算屬性還是 methods 取決於你是否需要快取,當遍歷大陣列和大量計算時,應當使用計算屬性,除非你不希望得到快取。