Vue 侦听器 watch
一.侦听器(watch)是什么?
Vue提供了一种更通用的方式来观察和响应Vue实列上的数据变动:侦听属性,当属性发生改变时,自动触发属性对应的侦听器。
当需要在数据变化时执行异步或开销较大的操作时,这个方法最有用
二.基础用法
当msg属性的值发生改变时,就会触发侦听器的执行
<div id="app">
<input type="text" v-model="msg">
</div>
<script>
let vm = new Vue({
el: '#app',
data: {
msg: 'Hello'
},
watch: {
msg: function() {
console.log(this.msg)
}
}
})
</script>
上述例子中当input中输入的内容变化时,把输入的内容在控制台中打印出来
三.侦听器扩展
1.立即触发回调
有下列代码:
<div id="app">
<p>FullName: {{fullName}}</p>
<p>FirstName: <input type="text" v-model="firstName"></p>
</div>
<script>
let vm = new Vue({
el: '#app',
data: {
firstName: 'first',
lastName: 'last',
fullName: ''
},
watch: {
firstName(newName, oldName) {
this.fullName = newName + ' ' + this.lastName;
}
}
})
</script>
上述代码中,当我们输入firstName后,wacth监听每次修改变化的新值,然后计算输出fullName。
这里 watch 的一个特点是,最初绑定的时候是不会执行的,要等到 firstName 改变时才执行监听计算
那么如果我们想要在最初绑定的时候就执行的话,则可以通过添加handler方法和immediate属性来实现,修改后的watch代码如下:
watch: {
firstName: {
handler(newName, oldName) {
this.fullName = newName + ' ' + this.lastName;
},
// 代表在wacth里声明了firstName这个方法之后立即先去执行handler方法
immediate: true
}
}
我们给fristName绑定了一个handler方法,之前watch方法的默认写的就是handler,Vue.js会去处理这个逻辑,最终编译出来就是handler,而immediate默认值为false,即为不执行也不触发回调,而true代表如果在 wacth 里声明了 firstName 之后,就会立即先去执行里面的handler方法
2.深度监听
受 JavaScript 的限制,Vue 无法检测到对象属性的变化
例如,在下面的输入框中输入数据改变 obj.a 的值是无效的
<div id="app">
<input type="text" v-model="obj.a">
</div>
<script>
let vm = new Vue({
el: '#app',
data: {
obj: {
a: 123
}
},
watch: {
obj: {
handler(newVal, oldVal) {
console.log('obj.a changed');
},
{
immediate: true
}
}
}
})
</script>
默认情况下 handler 只监听 obj 这个属性的引用的变化,只有给 obj 赋值时它才会被监听到
如果我们需要监听 obj 中的属性 a的话就需要使用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 设置监听函数
3.注销
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 }
)