1. 前言
本節介紹計算屬性的使用方法。包括什么是計算屬性,計算屬性的特點,還有計算屬性和方法在實際使用中的區別。其中重點掌握計算屬性和方法的區別,了解它之后,才能在日常工作中靈活使用計算屬性和方法。
2. 慕課解釋
計算屬性,就是當其依賴屬性的值發生變化時,這個屬性的值會自動更新,與之相關的 DOM 部分也會同步自動更新?!?官方定義
計算屬性實際上是一個方法,它可以完成各種復雜的邏輯,包括運算、函數調用等,并最終返回一個值。之前的章節中介紹了模版插值的語法,我們知道模板內的可以使用表達式進行計算,例如:{{ count * number }}
。但有時候我們的計算邏輯并非如此簡單,當模板中放入太多的復雜邏輯會讓模板過于繁瑣且難以維護。計算屬性 computed
的使用可以解決此類問題。 computed
在項目中會大量使用,在使用時需要注意的是 computed
必須有一個返回值。使用 computed
并不難,難點在于如何編寫其內部的復雜邏輯。
3. 寫一個計算屬性
前面介紹了什么是計算屬性,那么怎么去定義一個計算屬性呢?讓我們先來看一段代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<h1>商品數量:{{count}} 個</h1>
<h1>商品單價:{{unitPrice}} 元</h1>
<h1>商品總價:{{totalPrice()}} 元</h1>
</div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
count: 10,
unitPrice: 24
},
methods: {
totalPrice() {
return this.count * this.unitPrice
}
}
})
</script>
</html>
代碼解釋:上述例子中,模板語句中我們通過一定的邏輯運算得到了商品的總價。像這樣的算法我們可以使用計算屬性來實現,接下來我們用計算屬性來改寫這個例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<h1>商品數量:{{count}} 個</h1>
<h1>商品單價:{{unitPrice}} 元</h1>
<h1>商品總價:{{totalPrice}} 元</h1>
</div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
count: 10,
unitPrice: 24
},
computed: {
totalPrice() {
return this.count * this.unitPrice
}
}
})
</script>
</html>
代碼解釋:
第 14-16 行,我們定義了一個計算屬性 totalPrice
,它的返回值是商品的單價和數量相乘得到的總價,在 html 模板中,我們直接用插值表達式 {{ totalPrice }} 來獲得商品的總價,然后渲染到頁面上。
計算屬性的值會根據其函數內部依賴的變化而重新計算。也就是說,在上面的例子中當 count 和 unitPrice 有任意一方發生改變時 totalPrice 都會隨之更新,最后更新頁面。我們通過下面的例子來驗證這一點:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<h1>商品數量:{{count}} 個</h1>
<h1>商品單價:{{unitPrice}} 元</h1>
<h1>商品總價:{{totalPrice}} 元</h1>
<button @click="changePrice">修改單價</button>
<button @click="changeCount">修改數量</button>
</div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
count: 10,
unitPrice: 24
},
computed: {
totalPrice() {
return this.count * this.unitPrice
}
},
methods: {
changePrice() {
vm.unitPrice = vm.unitPrice + 1
},
changeCount() {
vm.count = vm.count + 1
}
}
})
</script>
</html>
代碼解釋:
第 5-7 行,我們在頁面中加入了修改單價和修改數量的兩個操作按鈕,每次點擊修改單價就對單價 unitPrice + 1,點擊修改數量就對數量 count + 1。當我們每次點擊時,可以發現商品總價的值都會發生改變,因此計算屬性的值會隨著依賴的變化而更新。
4. Getter 和 Setter
前面我們介紹了如何編寫一個簡單的計算屬性,接下來我們介紹了一下如何通過 getter 和 setter 來編寫一個復雜的計算屬性。
每一個計算屬性都包含一個 getter
和一個 setter
,我們上面的兩個示例都是計算屬性的默認用法,只是利用了 getter
來讀取。在你需要時,也可以提供一個 setter
函數 , 當手動修改計算屬性的值就像修改一個普通數據那樣時,就會觸發 setter
函數,執行一些自定義的操作。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<h1>全名: {{fullName}} </h1>
<h1>firstName: {{firstName}} </h1>
<h1>lastName: {{lastName}} </h1>
</div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
firstName: '',
lastName: ''
},
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>
</html>
代碼解釋:
上述代碼中我們定義了一個 fullName 的計算屬性,并定義了它的 getter 和 setter。
第 4-6行,setter: 每次修改 fullName 時將姓賦值給 firstName,將名賦值給 lastName。
第 8-11行,getter: 每次獲取 fullName 時將 firstName 和 lastName 拼接后返回。
我們打開控制臺,運行 vm.fullName = ‘John Doe’ 時 setter 會被調用,vm.firstName 和 vm.lastName 也會相應地被更新。在控制臺輸入 vm.firstName 回車可以看到它的值。
5. 計算屬性 VS 方法
如果不使用計算屬性,在 methods 里定義了一個方法,也可以實現相同的效果,甚至該方法還可以接受參數,使用起來更靈活。
例如:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<h1>商品數量:{{count}} 個</h1>
<h1>商品單價:{{unitPrice}} 元</h1>
<h1>商品總價:{{totalPrice()}} 元</h1>
</div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
count: 10,
unitPrice: 24
},
methods: {
totalPrice() {
return this.count * this.unitPrice
}
}
})
</script>
</html>
代碼解釋:
第 8-10 行,我們定義了一個方法 totalPrice
,它的返回值是商品的單價和數量相乘得到的總價,在 html 模板中,我們直接用插值表達式 {{ totalPrice() }} 來獲得商品的總價,然后渲染到頁面上。
既然 methods 同樣可以解決模板中復雜邏輯計算的問題,那么為什么還需要使用計算屬性呢?
原因就是:計算屬性是基于它的依賴緩存的。前面我們介紹過,計算屬性的改變取決于其所依賴數據的變化,所以只要依賴數據不發生改變,計算屬性就不會更新。當我們重復獲取計算屬性時它也不會重復計算,只會獲取緩存的值。而我們每次調用 methods 都會重新計算一遍,這樣將會消耗一部分性能。當然,如何你不希望對數據進行緩存,那么可以用方法來代替。
6. 小結
本節,我們帶大家學習了 computed 在 vue 項目中的運用。主要知識點有以下幾點:
- 通過計算屬性 computed 來代替在模板編寫復雜邏輯的使用方法。
- 如何利用 setter 和 getter 來編寫一個復雜的計算屬性。
- 對比了計算屬性和方法的區別:計算屬性是有緩存的而方法每次都會重新執行。