一、立即觸發回調
watch 最初綁定時是不會執行的,需要等監聽的內容改變時才執行監聽計算
那我們想要一開始綁定的時候就執行該怎么辦呢?
可以修改一下 watch 寫法,如下:
watch: { firstName: { handler(newName, oldName) { this.fullName = newName + ' ' + this.lastName; }, { immediate: true } } }
上述寫法用到了 handler 方法和 immediate 屬性
1、handler 方法
原來我們 watch 中默認寫的就是這個 handler,Vue 會去處理這個邏輯,最終編譯出來其實就是這個 handler
2、immediate 屬性
指定 immediate: true 將立即以表達式的當前值觸發回調,即在 wacth 中聲明了 firstName 之后就會立即執行里面的 handler 方法,如果為 false 就跟原來的效果一樣,不會在綁定的時候就執行
二、深度監聽
受 JavaScript 的限制,Vue 無法檢測到對象屬性的變化
例如,在下面的輸入框中輸入數據改變 obj.a 的值是無效的
<div>
<input type="text" v-model="obj.a">
</div>
new Vue({
el: '#root',
data: {
obj: {
a: 123
}
},
watch: {
obj: {
handler(newVal, oldVal) {
console.log('obj.a changed');
},
{ immediate: true }
}
}
})
默認情況下 handler 只監聽 obj 這個屬性的引用的變化,只有給 obj 賦值時它才會被監聽到
如果我們需要監聽 obj 中的屬性 a 該怎么做呢?這時候就需要用到 deep 屬性了
1、deep 屬性
watch 中有一個屬性 deep,默認值為 false,表示是否進行深度監聽
watch: { obj: { handler(newVal, oldVal) { console.log('obj.a changed'); }, { immediate: true, deep: true } } }
設置 deep 為 true 后,監聽器會一層層的往下遍歷,給對象的所有屬性都加上這個監聽器,這樣就可以監聽到屬性 a 了
但這樣性能消耗會非常大,只要修改 obj 中任一屬性都會觸發這個監聽器里的 handler,因此我們可以使用字符串形式監聽來進行優化:
watch: { 'obj.a': { handler(newVal, oldVal) { console.log('obj.a changed'); }, { immediate: true // deep: true } } }
這樣 Vue 會一層層解析下去,直到遇到屬性 a,然后才給 a 設置監聽函數
三、注銷
1、unwatch 方法
const unwatch = app.$watch('text', (newVal, oldVal) => { console.log('text changed'); }) unwatch(); // 手動注銷 watch
注意在帶有 immediate 選項時,不能在第一次回調時取消偵聽給定的 property
// 這會導致報錯 var unwatch = vm.$watch( 'value', function () { doSomething() unwatch() }, { immediate: true } )
如果仍想在回調內部調用一個取消偵聽的函數,應該先檢查其函數的可用性:
var unwatch = vm.$watch( 'value', function () { doSomething() if (unwatch) { unwatch() } }, { immediate: true } )
