本教程分為三部分 : 基礎(chǔ) 進階 實戰(zhàn) ,深入淺出Vue.
基礎(chǔ)篇持續(xù) 更新中
第三章 計算屬性
我們己經(jīng)可以搭建出一個簡單的
Vue應(yīng)用,在模板中雙向綁定一些數(shù)據(jù)或表達(dá)式了。但是表達(dá)式如果過長,或邏輯更為復(fù)雜時,就會變得雕腫甚至難以閱讀和維護。
<div id="app">
<!-- 需求 123 456 789 編程 789 456 123 -->
{{text}}
<!-- 邏輯過長,難以維護,所以遇到復(fù)雜的邏輯時 ,應(yīng)當(dāng)使用計算屬性 -->
<br> {{text.split(',').reverse().join(',')}}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
var app = new Vue({
el: "#app",
data: {
text: '123,456,789'
}
})
</script>
這里的表達(dá)式包含 3 個操作,并不是很清晰,所以在遇到復(fù)雜的邏輯時應(yīng)該使用 計算屬性
下面開始介紹 計算屬性的用法
所有的計算屬性都以函數(shù)的形式寫在 Vue實例內(nèi)的computed 選項內(nèi),最終返回計算后的結(jié)果。將上面的例子改成計算屬性
<div id="app">
<!-- 需求 123 456 789 編程 789 456 123 -->
{{text}}
<!-- 邏輯過長,難以維護,所以遇到復(fù)雜的邏輯時 ,應(yīng)當(dāng)使用計算屬性 -->
<br> {{text.split(',').reverse().join(',')}}<br>
<!-- 下面使用使用計算屬性得到的 -->
下面使用使用計算屬性得到的 {{ reverseText}}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
var app = new Vue({
el: "#app",
data: {
text: '123,456,789'
},
//計算屬性都會定義在`Vue`的實例`computed `中
computed: {
reverseText: function() {
return this.text.split(',').reverse().join(',')
}
},
})
</script>
在一個計算屬性里可以完成各種復(fù)雜的邏輯,包括運算、函數(shù)調(diào)用等,只要最終返回一個結(jié)果就可以。除了上例簡單的用法,
計算屬性還可以依賴多個 Vue 實例的數(shù)據(jù),只要其中任一數(shù)據(jù)變化,計算屬性就會重新執(zhí)行,視圖也會更新
下面看一個經(jīng)典的例子 ,計算兩個購物車的總價
<div id="app">
兩個購物車總計:{{ prices}}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
//需求 計算購物車中所有商品的總價
packagel1: [{
name: 'iphone',
price: 6999,
count: 2
}, {
name: 'ipad',
price: 3999,
count: 2
}
]
,
packagel2: [{
name: 'iphone8',
price: 6999,
count: 1
}, {
name: 'ipad',
price: 3999,
count: 20
}]
},
// 計算屬性
computed: {
prices: function() {
var prices = 0
for (var i = 0; i < this.packagel1.length; i++) {
prices += this.packagel1[i].price * this.packagel1[i].count
}
for (var j = 0; j < this.packagel2.length; j++) {
prices += this.packagel2[j].price * this.packagel2[j].count
}
return prices;
}
}
})
</script>
需要注意的是 :除了上例簡單的用法,計算屬性還可以依賴多個 Vue 實例的數(shù)據(jù)
<div id="app">
兩個購物車總計:{{ prices}}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
//除了上例簡單的用法,計算屬性還可以依賴多個 Vue 實例的數(shù)據(jù)
var app1 = new Vue({
el: '#app1',
data: {
msg: "我是另外一個實例數(shù)據(jù)"
}
})
var app = new Vue({
el: '#app',
data: {
//需求 計算購物車中所有商品的總價
packagel1: [{
name: 'iphone',
price: 6999,
count: 2
}, {
name: 'ipad',
price: 3999,
count: 2
}
]
,
packagel2: [{
name: 'iphone8',
price: 6999,
count: 1
}, {
name: 'ipad',
price: 3999,
count: 20
}]
},
// 計算屬性
computed: {
prices: function() {
var prices = 0
for (var i = 0; i < this.packagel1.length; i++) {
prices += this.packagel1[i].price * this.packagel1[i].count
}
for (var j = 0; j < this.packagel2.length; j++) {
prices += this.packagel2[j].price * this.packagel2[j].count
}
//依賴另外的Vue實例數(shù)據(jù) 會根據(jù)變化而變化
return prices + '------------------' + app1.msg;
}
}
})
</script>
只要其中任一數(shù)據(jù)變化,計算屬性就會重新執(zhí)行,視圖也會更新

getter和setter屬性
每一個計算屬性都包含一個 getter和一個 setter,我們上面的兩個示例都是計算屬性的默認(rèn)用法 , 只是利用了 getter來讀取。在你需要時,也可以提供一個 setter函數(shù) , 當(dāng)手動修改計算屬性的值就像修改一個普通數(shù)據(jù)那樣時,就會觸發(fā) set ter函數(shù),執(zhí)行一些自定義的操作
<div id="app1">
6666--------------- :{{fullName}}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
//除了上例簡單的用法,計算屬性還可以依賴多個 Vue 實例的數(shù)據(jù)
var app1 = new Vue({
el: '#app1',
data: {
firstName: "我是武當(dāng)山張",
lastName: '三瘋'
},
computed: {
//如果計算屬性直接跟一個function ,默認(rèn)的就是getter函數(shù)
/*fullName: function() {
return this.firstName + ' ' + this.lastName;
}*/ //和下面的寫法一樣
//設(shè)置全程名字 就要用set方法
fullName: {
get: function() {
return this.firstName + ' ' + this.lastName;
},
//可以執(zhí)行一些自定義的操作 用逗號進行分割 操作
set: function(newValue) {
var names = newValue.splic('.');
this.fullName = names[0];
this.lastName = names[1];
}
}
},
})
</script>
調(diào)用之前是張三瘋 調(diào)用之后 變成張無忌

計算屬性除了上述簡單的文本插值外,還經(jīng)常用于動態(tài)地設(shè)置元素的樣式名稱class和內(nèi)聯(lián)樣式style,后邊會詳細(xì)解讀
小技巧: 計算屬性還有兩個很實用的小技巧容易被忽略:一是計算屬性可以依賴其他計算屬性:
二是計算屬性不僅可以依賴當(dāng)前Vue實例的數(shù)據(jù),還可以依賴其他實例的數(shù)據(jù)
計算屬性緩存
調(diào)用·methods里的方法也可以與計算屬性起到同樣的作用
頁面中的方法: 如果是調(diào)用方法,只要頁面重新渲染。方法就會重新執(zhí)行,不需要渲染,則不需要重新執(zhí)行
計算屬性:不管渲染不渲染,只要計算屬性依賴的數(shù)據(jù)未發(fā)生變化,就永遠(yuǎn)不變。
<div id="app">
{{reverseText}} <br>
<hr>
<!-- //計算屬性緩存 顯示當(dāng)前時間距離1970年時間戳-->
當(dāng)前時間距離1970年時間戳--------{{now}}
<hr>
<!-- 通過methods拿到的時間戳(方法后面跟括號()) -->
通過methods拿到的時間戳 方法后面跟括號{{times()}}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
var app = new Vue({
el: "#app",
data: {
text: '123,456,789'
},
computed: {
//如果計算屬性直接跟一個function ,默認(rèn)的就是getter函數(shù)
reverseText: function() {
return this.text.split(',').reverse().join(',')
},
now: function() {
return Date.now()
}
},
methods: {
times: function() {
return Date.now()
}
},
})
</script>
頁面中的方法: 如果是調(diào)用方法,只要頁面重新渲染。方法就會重新執(zhí)行,不需要渲染,則不需要重新執(zhí)行
計算屬性:不管渲染不渲染,只要計算屬性依賴的數(shù)據(jù)未發(fā)生變化,就永遠(yuǎn)不變

結(jié)論: 沒有使用計算屬性,在 methods里定義了一個方法實現(xiàn)了相同的效果,甚至該方法還可以接受
參數(shù),使用起來更靈活。既然使用 methods就可以實現(xiàn),那么為什么還需要計算屬性呢?原因就是
計算屬性是基于它的依賴緩存的。 一個計算屬性所依賴的數(shù)據(jù)發(fā)生變化時,它才會重新取值,所以text 只要不改變,計算屬性也就不更新
何時使用: -----------使用計算屬性還是 methods 取決于你是否需要緩存,當(dāng)遍歷大數(shù)組和做大量計算時,應(yīng)當(dāng)使用計算屬性,除非你不希望得到緩存。