Vue3中监视reactive定义的响应式数据时oldValue无法正确获取的问题

文章详细探讨了在Vue3中使用watch监测ref和reactive定义的响应式数据时,oldValue无法正确获取的情况。通过六个不同场景的示例,解释了当监视reactive数据的全部属性或某个属性为对象时,oldValue总是指向同一个对象,导致无法正确获取旧值。解决方案包括使用计算属性转换响应式对象为ComputedRef。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

Vue3中监视reactive定义的响应式数据时oldValue无法正确获取的问题,我们分6种情况进行说明

我们简单在setup里面写一点数据做测试

<template>
	<h2>当前求和为:{{sum}}</h2>
	<button @click="sum++">点我+1</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+='~'">修改姓名</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',
		setup(){
			//数据
			let sum = ref(0)
			let msg = ref('你好啊')
			let person = reactive({
				name:'张三',
				age:18,
				job:{
                
					j1:{
						salary:20
					}
				}
			})
            // 情况1 监视ref所定义的一个响应式数据
            watch(sum,(newValue,oldValue)=> {
                console.log('sum变了',newValue,oldValue);
            },{immediate:true})
			
        
			return {
				sum,
				msg,
				person
			}
		}
	}

</script>


 

提示:以下是本篇文章正文内容,下面案例可供参考

一、监视ref所定义的一个响应式数据

当我们只是监视由ref定义的基本数据类型的时候,是可以监视到数据的新旧变化

watch(sum,(newValue,oldValue)=> {
                console.log('sum变了',newValue,oldValue);
            },{immediate:true})

由于我们配置了immediate:true,所以一上来就会先监听一次
在这里插入图片描述
控制台结果如下:

在这里插入图片描述

二、监视ref所定义的多个响应式数据

watch([sum,msg],(newValue,oldValue)=> {
                console.log('sum或msg变了',newValue,oldValue)
            },{immediate:true})

在这里插入图片描述
我们可以看到newValue 和 oldValue 的变化

在这里插入图片描述

三、监视reactive所定义的一个响应式数据的全部属性

 watch(person,(newValue,oldValue)=> {
                console.log('person变化了',newValue,oldValue)
                console.log(newValue === oldValue); // true
            },{deep:false}) 

当我们点击person的任意一个属性时
在这里插入图片描述
我们会发现没有办法正确的获取oldValue,并且 console.log(newValue === oldValue)打印的结果为真
在这里插入图片描述
这是为什么呢,是BUG还是vue3作者刻意设计的呢?我们接着看情况4

四、 监视reactive所定义的一个响应式数据中的某个属性

  watch(()=>person.name,(newValue,oldValue)=> {
                console.log('person的name变化了',newValue,oldValue)
            })

这个时候我们发现oldValue又是能正确的获得到,我们再来看看情况五

在这里插入图片描述

五、 监视reactive所定义的一个响应式数据中的某些属性

 watch([()=>person.name,()=>person.age],(newValue,oldValue)=> {
                console.log('person的name或age变化了',newValue,oldValue)
                console.log(newValue === oldValue); // false
            })

到这里oldValue也是正确的,此时小编若有所思,是不是只要监视的是某个对象的属性(前提是这个属性不能是对象),oldVlalue就是正常的,我们接着看情况六
在这里插入图片描述

六、 监视reactive所定义的一个响应式数据中的某个属性(这个属性是一个对象)

watch(()=>person.job,(newValue,oldValue)=> {
                console.log('person的job变化了',newValue,oldValue)
                console.log(newValue === oldValue); // true
            },{deep:true}) //此处由于监视的是reactive素定义的对象中的某个属性,所以deep配置有效 */

果然只要监视的是值本身是一个对象,就没法正确获得到oldValue
在这里插入图片描述
小编也验证了一下如果这里监视的是person.job.j1.salary,oldValue是能正确的获取到的。

总结

1、如果定义了reactive的数据,想去使用watch监听数据改变,则无法正确获取旧值,并且deep属性配置无效,自动强制开启了深层次监听。

2、如果使用 ref 初始化一个对象或者数组类型的数据,会被自动转成reactive的实现方式,生成proxy代理对象。也会变得无法正确取旧值。

3、用任何方式生成的数据,如果接收的变量是一个proxy代理对象,就都会导致watch这个对象时,watch回调里无法正确获取旧值。

4、本质是newvalue和oldvalue是指向同一个对象所以才会产生2者相同的情况,我们可以通过计算属性,将响应式对象转换为ComputedRef的响应式字符串,之后监听这个字符串,将解包后的旧值新值转为对象形式即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Front explorers

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值