偵聽器
偵聽屬性,響應數據(data&computed)的變化,當數據變化時,會立刻執行對應函數,
值類型
函數類型
例:
const vm = new Vue({
el: '#app',
data: {
msg: 'hello,你好呀,我是杉杉',
},
watch: {
msg () {
console.log('msg的值改變啦~');
}
}
})
// 更改msg的值
vm.msg = 'hello~~~~'; // 此時會在控制台中打印出` msg的值改變啦 `
偵聽器函數,會接收兩個參數,第一個參數為newVal(被改變的數據),第二個參數為oldVal(賦值新值之前的值)。如在上述代碼中,將偵聽器watch更改一下,如:
watch: {
msg (newVal,oldVal) {
conosle.log(newVal, oldVal);
}
}
// 更改msg的值
vm.msg = 'hello~~~~'; // 此時會在控制台中打印出`hello,你好呀,我是杉杉 hello~~~~`
字符串類型
值為方法名字,被偵聽的數據改變時,會執行該方法。
const vm = new Vue({
el: '#app'
data: {
msg: '杉杉'
},
watch: {
msg: 'msgChange'
},
methods: {
msgChange () {
console.log('msg的值改變啦');
}
}
})
vm.msg = 'hello'; // 此時msgChange函數會執行,控制台中打印出 ` msg的值改變啦 `
對象類型
寫成對象類型時,可以提供選項。
handler
必需。handler時被偵聽的數據改變時執行的回調函數。
handler的值類型為函數/字符串,寫成字符串時為一個方法的名字。
const vm = new Vue({
el: '#app'
data: {
msg: '杉杉'
},
watch: {
msg: {
handler () {
console.log('msg的值改變啦');
}
}
}
})
vm.msg = 'hello'; // 此時回調函數會執行,控制台中打印出 ` msg的值改變啦 `
deep
在默認情況下,偵聽器偵聽對象只偵聽引用的變化,只有在給對象賦值時它才能被監聽到。所以需要使用deep選項,讓其可以發現對象內部值的變化,將deep的值設置為true,那么無論該對象被嵌套的有多深,都會被偵聽到。
const vm = new Vue({
el: '#app'
data: {
personObj: {
name: '鄧旭明',
age: 88
}
},
watch: {
personObj: {
handler () {
console.log('對象的值改變啦');
},
deep: true // 開啟深度偵聽
}
}
})
vm.obj.name = '老鄧頭'; // 此時回調函數會執行,控制台中打印出 ` 對象的值改變啦 `
注意,當對象的屬性較多的時候,性能開銷會比較大,此時可以監聽對象的某個屬性,這個后面再說。
immediate
加上immediate選項后,回調將會在偵聽開始之后立刻被調用。而不是等待偵聽的數據更改后才會調用。
const vm = new Vue({
el: '#app'
data: {
msg: '杉杉'
},
watch: {
msg: {
handler () {
console.log('回調函數執行啦');
},
immediate: true
}
}
})
// 此時未更改msg的值,就會在控制台打印出來` 回調函數執行啦 `
數組類型
可以將多種不同值類型寫在一個數組中。如:
const vm = new Vue({
el: '#app'
data: {
msg: '杉杉'
},
watch: {
msg: [
'msgChange',
function () {},
{
handler () {},
deep: true,
immediate: true
}
]
}
})
鍵類型
正常對象key值
以上演示的都是正常的對象key值,這里不再贅述。
字符串類型key值
當key值類型為字符串時,可以實現監聽對象當中的某一個屬性,如:
const vm = new Vue({
el: '#app'
data: {
personObj: {
name: '鄧旭明',
age: 88
}
},
watch: {
'personObj.name' () {
console.log('對象的值改變啦');
}
}
})
vm.obj.name = '老鄧頭'; // 此時回調函數會執行,控制台中打印出 ` 對象的值改變啦 `
vm.$watch
Vue實例將會在實例化時調用$watch,遍歷watch對象的每一個屬性。
我們也可以利用vm.$watch來實現偵聽,用法與watch選項部分一致,略有不同。以下為使用方法。
- 偵聽某個數據的變化
// 1. 三個參數,一參為被偵聽的數據;二參為數據改變時執行的回調函數;三參可選,為設置的選項對象
vm.$watch(
'msg',
function () {
// 干了點事兒
},
{
deep: Boolean,
immediate: Boolean
}
)
// 2. 二個參數,一參為被偵聽的數據;二參為選項對象,其中handler屬性為必需,是數據改變時執行的回調函數,其他屬性可選。
vm.$watch(
'msg',
{
handler () {
// 干了點事兒
},
deep: Boolean,
immediate: Boolean
}
)
- 偵聽某個對象屬性的變化
vm.$watch('obj.name', /**參數和上面一之*/)
- 當監聽的數據的在初始不確定,由多個數據得到時,此時可以將第一個參數寫成函數類型
vm.$watch(function () {
// 表達式`this.a + this.b`每次得出一個不同的結果時該函數都會被調用
// 這就像監聽一個未被定義的計算屬性
return this.a + this.b;
}, /**參數和上面一致*/)
偵聽器函數執行后,會返回一個取消偵聽函數,用來停止觸發回調:
const unwatch = vm.$watch('msg', function () {});
unwatch(); // 執行后會取消偵聽msg數據
使用unwatch時,需要注意的是,在帶有immediate選項時,不能在第一次回調時取消偵聽數據。
const unwatch = vm.$watch('msg', function () {
// 干了點兒事
unwatch(); // 此時會報錯
},{
immediate: true
}
})
如果仍然希望在回調內部用一個取消偵聽的函數,那么可以先檢查該函數的可用性:
var unwatch = vm.$watch('msg', function () {
// 干了點兒事
if(unwatch) {
unwatch();
}
},{
immediate: true
}
})
偵聽器 vs 計算屬性
-
兩者都可以觀察和響應Vue實例上的數據的變動。
-
watch擅長處理的場景是:一個數據影響多個數據。計算屬性擅長處理的場景是:多個數據影響一個數據。
-
在偵聽器中可以執行異步,但是在計算屬性中不可以,例:
使用偵聽器:
var vm = new Vue({
el: '#app',
data: {
question: '',
},
watch: {
question () {
setTimeout(() => {
alert(this.question);
}, 1000)
}
}
})