vue3 watch侦听器填坑详细分析 附加实例
两个小“坑”:
- 监视reactive定义的响应式数据时:oldValue无法正确获取、强制开启了深度监视(deep配置失效)。
- 监视reactive定义的响应式数据中某个属性时:deep配置有效。
如果监听reactive所定义的响应式中的某些属性 watch第一个参数要传一个函数 返回值为要监听的对象属性
watch(() => person.age, (nv, ov) => {
console.log('person的age变了', nv, ov);
})
<template>
<h1>当前求和为:{{ sum }}</h1>
<button @click="sum++">点我加一</button>
<hr/>
<h2>当前的信息为:{{ msg }}</h2>
<button @click="msg += '!'">修改信息</button>
<hr/>
<h2>姓名:{{ person.name }}</h2>
<h2>年龄:{{ person.age }}</h2>
<h2>薪资:{{ person.job.j1.salary }}K</h2>
<button @click="person.name = person.name + '~'">修改姓名</button>
<button @click="person.age++">增长年龄</button>
<button @click="person.job.j1.salary++">增长薪资</button>
</template>
<script>
import { ref, reactive, watch } from 'vue';
export default {
name: 'Demo',
//vue2中的watch写法
// watch:{
//简单写法
// sum(nv,ov){
// console.log('sum的值发生变化了');
// console.log(`newValue:${nv}, oldValue:${ov}`);
// }
//完整写法
// sum:{
// deep: true, //深度监视
// immediate: true, //一开始就监视一下
// handler(nv,ov){
// console.log('sum的值发生变化了');
// console.log(`newValue:${nv}, oldValue:${ov}`);
// }
// }
// },
setup(){
let sum = ref(0);
let msg = ref('你好');
let person = reactive({
name: '张三',
age: 18,
job:{
j1:{
salary: 20
}
}
})
// //情况一: 监视ref所定义的响应式数据
watch(sum, (nv, ov) => {
//这里我并不需要this,所以剪头函数,普通函数我可以乱粥
console.log('sum的值发生变化了');
console.log(`newValue:${nv}, oldValue:${ov}`);
}, {
//监视的配置
immediate: true //一上来就更新
});
//情况二:监视ref所定义的多个响应式数据
// watch([sum, msg], (nv, ov) => {
// //此时nv和ov都是被监视属性值的数组
// // console.log(Array.isArray(ov)); //true
// console.log('sum的值或者msg的值发生变化了');
// console.log(`newValue:${nv[0]},${nv[1]}, oldValue:${ov}`);
// },{
// immediate: true
// });
/**
* 情况三:监视reactive所定义的一个响应式数据
* 坑:1.此处无法获取正确的ov(oldValue)
* 2.强制开启了深度监视
*/
// watch(person, (nv, ov) => {
// console.log('person变化了');
// console.log(nv, ov);
// }, {
// deep: false //此处的deep配置是无效的
// });
//情况四:监视reactive所定义的响应式中的某一个属性
// watch(() => person.age, (nv, ov) => {
// console.log('person的age变了', nv, ov);
// })
//情况五:监视reactive所定义的响应式中的某些属性:并不只是一个
// watch([() => person.age, () => person.name], (nv, ov) => {
// //此时nv和ov都是数组
// console.log('person的age或name发生改变了',nv, ov);
// });
//特殊情况
// watch(() => person.job, (nv, ov) => {
// //这里依然无法拿到正确的ov,因为依然监视的是对象
// console.log('person的job信息发生改变了',nv, ov);
// }, {
// //这里必须要加deep:true注意
// deep: true //此处因为监视的是reactive所定义的响应式对象的一个属性(这个属性的值它依然是一个对象),所以deep配置有效
// })
//返回一个对象
return {
sum,
msg,
person
}
}
}
</script>
<style>
</style>
.watchEffect函数
-
watch的套路是:既要指明监视的属性,也要指明监视的回调。
-
watchEffect的套路是:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性。
-
watchEffect有点像computed:
- 但computed注重的计算出来的值(回调函数的返回值),所以必须要写返回值。
- 而watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值。
//watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调。 watchEffect(()=>{ const x1 = sum.value const x2 = person.age console.log('watchEffect配置的回调执行了') })//watchEffect //不确定监视对象 //默认开启了immediate:true watchEffect(() => { console.log(`watch effect指定的回调执行了!!`) //依赖收集,你用到了谁它就监视谁!! //这里用到sum, person.job.j1.salary了,所以可以被监视到(只要它们发生变化就重新执行watchEffect) //与computed有点类似,依赖收集.(侧重点不一致,watchEffect注重过程,而computed注重计算函数的返回值) const x1 = sum.value; const x2 = person.job.j1.salary; })

浙公网安备 33010602011771号