說說 Vue.js 的計算屬性
1 應用場景
Vue.js 的表示式如果因為邏輯複雜變得過長時,就會變得臃腫,以至於難以閱讀和維護。
這裡我們對一個以分號分隔的字串做逆序處理,並修改分隔符為逗號的表示式。
html:
<div id="app"> {{str.split(';').reverse().join(',')}} </div>
js:
var app=new Vue({ el:'#app', data:{ str:'1;2;3' } });
輸出結果:
3,2,1
使用計算屬性之後——
html:
<div id="app2"> {{reversedStr}} </div>
js:
var app2 = new Vue({ el: '#app2', data: { str: '1;2;3' }, computed: { reversedStr: function () { return this.str.split(';').reverse().join(','); } } });
所有的計算屬性都以函式的形式定義在 Vue 例項內的 computed 屬性內,這些函式最終會返回計算後的結果 。
2 依賴多個數據
計算屬性還可以依賴 data 屬性內的多個數據,只要其中任一資料發生變化,計算屬性就會重新執行,檢視也會得到相應的更新。我們以購物車內兩種的物品為例,說說如何通過計算屬性來計算購買商品的總價:
html:
<div id="app"> 購買的商品:{{commodity1.name}} * {{commodity1.count}}、{{commodity2.name}} * {{commodity2.count}},總價:{{totalPrice}} </div>
js:
<script> var app = new Vue({ el: '#app', data: { commodity1: { name: 'Bose SoundSport Free 真無線藍芽耳機', price: 1998, count: 1 }, commodity2: { name: 'Kindle paperwhite 電子書閱讀器', price: 998, count: 2 } }, computed: { totalPrice: function () { return this.commodity1.price * this.commodity1.count + this.commodity2.price * this.commodity2.count; } } }); </script>
輸出結果:
購買的商品:Bose SoundSport Free 真無線藍芽耳機 * 1、Kindle paperwhite 電子書閱讀器 * 2,總價:3994
當 commodity1 或 commodity2 中的商品有任何變化,比如購買數量變化或價格調整時,計算屬性 totalPrice 就會自動更新。
3 get 與 set 函式
每一個計算屬性都包含一個 getter 和 setter,之前的示例只是利用了 getter 來讀取計算結果。在需要時,我們可以提供一個 setter 函式,當手動修改計算屬性的值時,就會觸發 setter 函式,可以在此函式中定義一些操作。例如:
html:
<div id="app2"> 商品總價:{{totalPrice}} </div>
js:
var app2 = new Vue({ el: '#app2', data: { price: 28, count: 3 }, computed: { totalPrice: { get: function () {//讀取 return this.price * this.count; }, set: function (val) {//寫入 var array = val.split(','); this.price = array[0]; this.count = array[1]; } } } }); app2.totalPrice = '30,3';
輸出結果:
商品總價:90
絕大多數情況下,只會用預設的 getter 方法來讀取計算屬性的值,很少用到 setter ,所以在宣告一個計算屬性時,可以直接使用之前介紹的預設寫法O(∩_∩)O~
4 依賴其它 Vue 例項
還可以依賴其它 Vue 例項中的資料或計算屬性。
html:
<div id="app3"> 最終價格:{{actualPrice}} </div>
js:
var app3 = new Vue({ el: '#app3', data: {}, computed: { actualPrice: function () { return app2.totalPrice * 0.8; } } });
輸出結果:
最終價格:72
注意:引用的 Vue 例項必須在呼叫之前就已經定義好。
5 快取
之前的示例程式碼,呼叫 methods 裡定義的方法也可以起到與計算屬性相同的作用。
既然使用 methods 就可以實現,那麼為什麼還需要用到計算屬性呢?原因就是計算屬性是基於它的依賴做了快取。一個計算屬性所依賴的資料發生變化時,它才會重新取值。
我們先定義一個休眠函式:
/** * 休眠 * @param n 休眠時間,單位為毫秒 */ function sleep(n) { var start = new Date().getTime(); while (true) { if (new Date().getTime() - start > n) { break; } } }
因為 js 是單執行緒的, 所以我們這裡使用 while(true) {}
,使得 whlie(){}
後面的程式被阻塞,從而實現休眠 。
js:
var app4 = new Vue({ el: '#app4', data: {}, computed: { now: function () { return Date.now(); } } }); console.log("app4.now:" + app4.now); sleep(3000); console.log("app4.now2:" + app4.now); var app5 = new Vue({ el: '#app5', data: {}, methods: { now: function () { return Date.now(); } } }); console.log("app5.now:" + app5.now()); sleep(3000); console.log("app5.now2:" + app5.now());
輸出結果:

從結果中可以看出:計算屬性 now 沒有變化。但 methods 不同,只要重新呼叫,函式就會被執行。
當遍歷大陣列或做大量計算時,建議使用自帶快取功能的計算屬性哦O(∩_∩)O~