在vue3中使用watch 来监听某个数据的变化, 因为我们定义数据的时候有 ref 和 reactive 两种方法, 所以watch 也会分出不同的五种情况
当使用 watch 来监听 ref 定义的数据时
<template>
<div> sum: {{sum}}</div>
<button @click="sum++">sum变化</button>
<div> msg: {{msg}}</div>
<button @click="msg+='!'">msg 变化</button>
</template>
<script>
import {ref,reactive,watch} from "vue";
export default {
name: 'App',
setup(){
let sum = ref(0);
let msg = ref("你好啊");
// watch(sum,(newvalue,oldvalue)=>{
// console.log("sum发生了变化",newvalue,oldvalue);
// })
//两个变量一起监听
watch([sum,msg],(newvalue,oldvalue)=>{
console.log(newvalue); //此时的 newvalue 是一个数组
console.log(oldvalue); //此时的 oldvalue 是一个数组
})
return {
sum,
msg
}
},
}
</script>
从上面的代码中, 我们可以看到, 如果我们只监听一个数据的时候可以使用
watch(sum,(newvalue,oldvalue)=>{
//逻辑代码
},{immediate:true})
如果我们要监听两个或多个数据, 最简单的方法就是 多写一个 watch 就可以了
还可以使用 数组的方式
watch([sum,msg],(newvalue,oldvalue)=>{
console.log(newvalue); //此时的 newvalue 是一个数组
console.log(oldvalue); //此时的 oldvalue 是一个数组
},{immediate:true})
当我们使用 watch 去监听一个 reactive定义的数据
<template>
<div>person:{{person}}</div>
<button @click="person.name+='!'">person name改变</button>
<br/>
<button @click="person.age+=1">person age改变</button>
<br/>
<button @click="person.job.j1.salary++">person job j1 salary 改变</button>
<br/>
<button @click="person.job.j2.salary++">person job j2 salary 改变</button>
</template>
<script>
import {ref,reactive,watch} from "vue";
export default {
name: 'App',
setup(){
let person = reactive({
name:"黄哥",
age:38,
job:{
j1:{
salary:20
},
j2:{
salary:50
}
}
})
watch(person,(newvalue,oldvalue)=>{
console.log("发现了person发生了变化",newvalue,oldvalue)
},{immediate:true,deep:false})
watch(()=>person.age,(newvalue,oldvalue)=>{
console.log(newvalue,oldvalue)
})
watch([()=>person.name,()=>person.age],(newvalue,oldvalue)=>{
console.log(newvalue,oldvalue)
})
watch(()=>person.job,(newvalue,oldvalue)=>{
console.log(newvalue,oldvalue);
},{deep:true})
watch(()=>person.job.j1.salary,(newvalue,oldvalue)=>{
console.log(newvalue,oldvalue)
})
return {
person
}
},
}
</script>
从上面的代码我们可以分现多种情况
情况一 整体监听 person 对象
watch(person,(newvalue,oldvalue)=>{
console.log("发现了person发生了变化",newvalue,oldvalue)
},{immediate:true,deep:false})
这里的 person 强制开启了 deep:true , 上面虽然配置了 deep:false, 但是是没有用的,同时还有一个小bug , 这里只能得到 newvalue, oldvalue 是得不到了, 如果实在需要 oldvalue 的话, 可以对每个属性单独监听
情况二 监听其中的某一个属性
watch(()=>person.age,(newvalue,oldvalue)=>{
console.log(newvalue,oldvalue)
})
watch 的第一个参数有三种形式, 第一种, ref或reactive 定义的数据, 第二种, 可以是一个数组,第三种, 也可以是一个回调函数
所以, 这里如果 写成 watch(person.age,…) 这种写法是错误的
正确的写法是 watch(()=>return person.age,…) 简化的写法就是 watch(()=> person.age)
情况三,监听多个属性,这里要使用 回调函数加数组的方式了
watch([()=>person.name,()=>person.age],(newvalue,oldvalue)=>{
console.log(newvalue,oldvalue)
})
其原因和情况二差不多, 不用多说了
情况四 如果监听 person , 是默认强制开启的 {deep:true},配不配deep都是一样的;但如果监听的是 person 内部的对象数据的时候, 是可以使用 deep 来配置的
watch(()=>person.job,(newvalue,oldvalue)=>{
console.log(newvalue,oldvalue);
},{deep:true})
上面的代码中, 我们更改的是 person.job.j1.salary 发生改变, 但是这里监听的是 person.job, 所以如果我们不配置 deep:true, 则是不可以监听到数据变化的
情况五
watch(()=>person.job.j1.salary,(newvalue,oldvalue)=>{
console.log(newvalue,oldvalue)
})
这种和情况二是差不多的。只不过是更深层的数据