侦听属性,响应数据(data&computed)的变化,当数据变化时,会立刻执行对应函数,
虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch
选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
值类型
函数类型
例:
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', /**参数和上面一之*/)
- 当监听的数据的在初始不确定,由多个数据得到时,此时可以将第一个参数写成函数类型
const vm = new Vue({
el: '#app',
data: {
num1:10,
num2:20,
},
computed:{
sum(){
return this.num1 + this.num2;
}
},
})
const unwatch = vm.$watch(
'sum',
function(){
console.log('sum 改变啦')
unwatch()
}
)
侦听器函数执行后,会返回一个取消侦听函数,用来停止触发回调:
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)
}
}
})