前言
計算屬性概念
顧名思義,首先它是一種屬性,其次它有“計算”這個特殊性質。每次取得它的值得時候,它并不像普通屬性那樣直接返回結果,而是經過一系列的計算之后再返回結果。
從這種角度考慮,其實它和 ES5 中的 getter
有著“血親關系”,事實上,vue 中的很多實現也是依賴于 getter
和 setter
的。
var vm = new Vue({
el: '#example',
data: {
firstName: 'Dale',
lastName: 'He'
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName;
}
}
});
這里就是最典型的計算屬性,當需要讀取 fullName
“屬性”的時候,我們去讀取了實例對象上的 firstName
和 lastName
屬性,然后進行了字符串的拼接操作,經歷了以上一系列的計算,將最終得到的結果作為 fullName
“屬性”的值,也即是 "Dale He"。
計算屬性(代理模式)
雖然這里可能不完全符合設計模式中的代理模式,但從它在讀取屬性之時,先進行了一定量計算,再返回需要的結果,這個計算的過程,實際上我們就可以認為是在為這個屬性添加了一個代理。每次讀寫一個屬性的時候,都先經歷代理中的計算操作。vue 默認添加了 getter
,也即是“讀”的代理,通過如下代碼,也可以添加“寫代理”。
var vm = new Vue({
el: '#example',
data: {
firstName: 'Dale',
lastName: 'He'
},
computed: {
fullName: {
get: function () {
return this.firstName + ' ' + this.lastName;
},
set: function (newValue) {
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
});
讀的時候,和前面一樣,直接返回字符串拼接結果;寫的時候,直接更新讀的時候它的源數據 firstName
和 lastName
,這樣三個屬性就都會自動更新過來。
觀察者(觀察者模式)
這個就比較明確了,從它的名字就可以知道。vue 框架本身作為調度中心,使得開發者只需要關注兩個核心主體——被觀察者以及被觀察者變化之后所需要采取的操作。
var vm = new Vue({
el: '#example',
data: {
firstName: 'Dale',
lastName: 'He'
},
watch: {
firstName: function () {
console.log('firstName changed!');
},
lastName: function () {
console.log('lastName changed!');
}
}
});
這里,將 firstName
和 lastName
作為被觀察者,watch
方法中為二者定義了當它們發生變動時所需要添加的操作,這里只進行了 console.log
打印,開發者可以根據自身需要完成更為復雜的功能。
計算屬性 VS 觀察者(watcher)
vue.js 官網上面,就計算屬性和觀察者兩個之間的關系和取舍說了很多東西,但是感覺具體其實還是沒有說明白。因為兩個雖然某些場合下可以實現相同的功能,但如前面所述,二者所代表的核心思想確實截然不同。
計算屬性是在讀寫一個屬性的時候,添加了一層攔截,使得我們能夠在讓這個屬性變得可以“計算”,雖然一方面它可以像一個普通屬性直接取值,但是另一方面,它更像一個函數,可以包含大量計算操作。
觀察者則是為一個屬性添加了一個監聽,當這個屬性發生變化的時候,開發者可以得到得知并采取一定的措施。
結語
雖然計算屬性和觀察者實現思路上有所不同,但是有的情況下,他們可以實現類似的功能,連帶的通過 methods
也一樣。官網上也給出了對照。例如實現通過 firstName
和 lastName
得到 fullName
這個最簡單的例子:
- 計算屬性,便捷,可緩存,性能較好;
- 觀察者,需要添加多個監聽,較為麻煩;
- methods,不能緩存,每次都會計算,性能較差
但是這里也并不是說,我們非得使用計算屬性而棄用觀察者和 methods
,觀察者和 methods
都有各自的特性。沒有最好的,只有最合適的~