一、立即触发回调
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 } )