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

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

文章目录

  • 前言
  • 一、监视ref所定义的一个响应式数据
  • 二、监视ref所定义的多个响应式数据
  • 三、监视reactive所定义的一个响应式数据的全部属性
  • 四、 监视reactive所定义的一个响应式数据中的某个属性
  • 五、 监视reactive所定义的一个响应式数据中的某些属性
  • 六、 监视reactive所定义的一个响应式数据中的某个属性(这个属性是一个对象)
  • 总结


前言

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,所以一上来就会先监听一次
在这里插入图片描述
控制台结果如下:

Vue3中监视reactive定义的响应式数据时oldValue无法正确获取的问题_第1张图片

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

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

Vue3中监视reactive定义的响应式数据时oldValue无法正确获取的问题_第2张图片
我们可以看到newValue 和 oldValue 的变化

Vue3中监视reactive定义的响应式数据时oldValue无法正确获取的问题_第3张图片

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

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

当我们点击person的任意一个属性时
Vue3中监视reactive定义的响应式数据时oldValue无法正确获取的问题_第4张图片
我们会发现没有办法正确的获取oldValue,并且 console.log(newValue === oldValue)打印的结果为真
Vue3中监视reactive定义的响应式数据时oldValue无法正确获取的问题_第5张图片
这是为什么呢,是BUG还是vue3作者刻意设计的呢?我们接着看情况4

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

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

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

Vue3中监视reactive定义的响应式数据时oldValue无法正确获取的问题_第6张图片

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

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

到这里oldValue也是正确的,此时小编若有所思,是不是只要监视的是某个对象的属性(前提是这个属性不能是对象),oldVlalue就是正常的,我们接着看情况六
Vue3中监视reactive定义的响应式数据时oldValue无法正确获取的问题_第7张图片

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

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

果然只要监视的是值本身是一个对象,就没法正确获得到oldValue
Vue3中监视reactive定义的响应式数据时oldValue无法正确获取的问题_第8张图片
小编也验证了一下如果这里监视的是person.job.j1.salary,oldValue是能正确的获取到的。

总结

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

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

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

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

你可能感兴趣的:(javascript,vue.js,前端)