两个小“坑”:
- 监视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; })