目錄
之前做過關於數據不是定值,而是由其他數據計算而得來的頁面。
以前學藝不精,只會一些Vue的簡單用法,所以之前都是用的methods方法,在輸入框上綁定input或者change事件,輸入數據時,修改結果的效果,來達到數據動態由其他數據計算得來的。
后來隨着Vue的使用越來越多,對Vue的其他知識點也開始逐漸多了解一點,這次做頁面上的計算,用了Watch偵聽器,這里簡單記錄一下自己在使用過程中遇到的問題和一些總結。
1.computed計算屬性
說到Watch偵聽器,就順便記錄一下computed計算屬性。
1.1. computed的簡單例子
之前就覺得computed計算屬性和直接在methods定義方法很類似,用computed可以實現的功能,直接定義方法好像基本都可以實現。
就像下面的簡單例子,做一個加法運算,computed計算屬性和methods的方法都是一樣的。
var vm = new Vue({
el: '#app',
data: {
a: 1,
b: 2
},
computed: {
returnAdd: function () {
return this.a + this.b;
}
},
methods: {
add: function () {
return this.a + this.b;
}
}
})
如下圖,兩個運算都是沒問題的。
計算屬性是基於它們的響應式依賴進行緩存的。只在相關響應式依賴發生改變時它們才會重新求值。
Vue官方文檔是這樣解釋的,計算屬性依賴於緩存,只要你的值沒有變,計算屬性都會返回之前緩存中的結果,適用一些需要進行大量計算的方法,如果不需要緩存,還是methods方便些。
1.2.computed計算屬性的setter
文檔后面還講到了計算屬性可以提供一個setter,就像下面這樣。
computed: {
returnAdd: {
// getter
get: function() {
this.sumAB_getter = this.a + this.b;
return this.a + this.b;
},
// setter
set: function(newVal) {
console.log('returnAdd-setter:' + newVal);
this.sumAB_setter = newVal;
}
}
},
我試了一下,getter會在returnAdd的值手動修改的時候觸發,但在計算后getter修改時不會觸發,目前也沒見別人用過,不是很清楚setter的用途。
2.Watch偵聽器
偵聽屬性Watch,當你有一些數據需要隨着其它數據變動而變動時,就可以使用Watch來監聽他們之間的變化。
2.1.簡單的watch偵聽
這里以上面的加法為例,使用watch做加法計算:
watch: {
a: function(n, o){
this.sumAB_watch = n + this.b;
console.log('a-newValue:' + n, 'a-oldValue:' + o, 'sumAB_watch:' + this.sumAB_watch);
},
b: function(n, o){
this.sumAB_watch = this.a + n;
console.log('b-newValue:' + n, 'b-oldValue:' + o, 'sumAB_watch:' + this.sumAB_watch);
},
},
監聽a和b的值,第一個參數是修改后的值,第二個參數是修改前的值,這樣就能監聽數據變化來做計算了。
不過這里還有個問題,就是頁面剛加載時,因為沒有變化,所以不會執行。
這里就引申出了另外的知識:handler方法和immediate屬性。
2.2.handler、immediate
其實之前寫的watch方法默認就是handler,而當immediate屬性為true時,就會先執行handler方法。
watch: {
a: {
handler(n, o){
this.sumAB_watch = n + this.b;
console.log('a-newValue:' + n, 'a-oldValue:' + o, 'sumAB_watch:' + this.sumAB_watch);
},immediate: true
},
b: {
handler(n, o){
this.sumAB_watch = this.a + n;
console.log('b-newValue:' + n, 'b-oldValue:' + o, 'sumAB_watch:' + this.sumAB_watch);
},immediate: true
}
},
這樣就會在頁面加載時先執行一次,如下圖。
2.3.監聽對象、數組等(deep屬性)
在監聽對象時,會有一個問題,修改對象的值的時候,不會觸發handler方法。
數組則可以觸發,但是修改前的值和修改后的值是一樣的,這里我暫時不清楚是什么問題。
var vm = new Vue({
el: '#app',
data: {
obj: {
x: 10,
y: 20
},
arr: [1, 2, 3, 4]
},
watch: {
obj: {
handler(n, o){
console.log('obj-newValue:' + n, 'obj-oldValue:' + o,);
}
},
arr: {
handler(n, o){
console.log('arr-newValue:' + n, 'arr-oldValue:' + o,);
}
}
}
})
這里修改對象的值不會觸發。
這時候就要用到deep屬性,設置deep屬性為true,監聽器就會深入觀察,向下遍歷,性能開銷可能會比較大。
obj: {
handler(n, o){
console.log('obj-newValue:' + JSON.stringify(n), 'obj-oldValue:' + JSON.stringify(o),);
},
deep: true
},
這時候就能觀察到對象內的數據變化了。
這里還有遇到一個小問題,如果監聽器新增一個obj.z = obj.x + obj.y 的計算,這里監聽了整個obj的變化,這樣計算完成后,因為obj.z的變化,還會再執行一次,所以我覺得如果監聽了整個對象的話,計算結果還是不要寫到這個對象里面去,以免增加不必要的開銷。
2.4.監聽字符串形式
如果不想監聽obj中其他值,只想監聽obj.x的值的變化,可以寫成字符串形式監聽。
'obj.x': {
handler(n, o){
console.log('obj.x-newValue:' + JSON.stringify(n), 'obj.x-oldValue:' + JSON.stringify(o),);
}
},
2.5.監聽多個對象
有時一個值可能是根據多個對象中的值,共同計算出來的,可以把這些改變的值放到一個對象中去,也可以直接監聽多個對象。
watch: {
twoObj:{
handler: function(val) {
console.log('two change: ', val)
},
deep: true
}
},
computed: {
twoObj(){
const { obj, obj2 } = this;
return {
obj,
obj2
}
}
},
這里是參考了 vue watch怎樣同時監聽兩個值的變化並執行方法 這篇文章。
以上就是我在寫關於監聽器的經驗和遇到問題,在這里簡單做下記錄,以后還可以多翻翻看,也希望對不懂的人有點小小的幫助。