Vue3修改reactive属性后两次console.log打印值相同问题
问题产生原因
这个现象不是Vue3的响应式异常,是两个机制共同导致的:
reactive()返回的是目标对象的Proxy代理实例,本质属于引用类型,所有对这个对象的访问、修改都指向同一块内存空间,不存在赋值时的快照拷贝。- 浏览器控制台对引用类型值的
console.log打印采用懒读取机制:执行打印语句时不会立刻序列化对象内容存储快照,只会在你首次点击展开这条打印记录时,才去读取对象当前的内存值渲染详情。
所以你在两次打印语句之间修改了对象属性,等到你在控制台展开查看两条日志时,读到的已经是修改完成后的对象状态,自然会看到两次打印的对象值完全一致。
这个行为和Vue无关,纯JS环境下可以直接复现:
const obj = { a: 0, b: { c: 1 } } console.log(obj, "第一次打印") obj.a = 10 console.log(obj, "第二次打印")控制台展开两条日志后,看到的a值均为10。
正确打印各时间点对象实际值的方案
核心思路是打印时生成当前对象的独立快照,断开和原对象的引用关联,常用方法如下:
- 深拷贝生成快照后打印
优先使用浏览器原生支持的structuredClone()做深拷贝,支持绝大多数JS数据类型(包括嵌套对象、数组、Date、Map、Set等),不会受后续原对象修改影响:
如果需要兼容极低版本浏览器,也可以用const ob1 = reactive({ a: 0, b: { c: 1 } }) console.log(structuredClone(ob1), "修改前快照") ob1.a = 10 console.log(structuredClone(ob1), "修改后快照")JSON.parse(JSON.stringify(ob1))做深拷贝,注意这个方法无法序列化函数、Symbol、循环引用的对象。 - 直接打印序列化后的字符串
临时调试时可以直接把对象转成格式化JSON字符串打印,字符串是基础类型,打印后就不会再变化:console.log(JSON.stringify(ob1, null, 2), "修改前") - 打印具体的基础类型属性
如果只需要观测单个属性的值,直接访问属性打印即可,基础类型是值传递,不存在引用关联问题:console.log(ob1.a, ob1.b.c, "修改前属性值")
内容的提问来源于stack exchange,提问作者tr93
相关产品推荐
相关产品推荐

