一、立即觸發回調
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 } )