Vue3组合式API中修改克隆响应式对象影响原对象如何解决
问题根因
这个问题和Vue3的Proxy响应式系统无关,是原生JavaScript的引用类型浅拷贝特性导致的:
- 你用扩展运算符
[...arr]做的数组拷贝属于浅拷贝:只会复制数组的第一层结构,数组内存储的对象依然是指向同一内存地址的引用 - 你的
setSummary方法在汇总时,直接修改了原对象的amount属性,还直接把原对象推入了汇总结果数组,没有创建新的独立对象,所有指向这些对象的数组(debits、浅拷贝得到的summary)都会同步感知到属性变化。
修复方法
不需要引入额外的深拷贝工具,针对你的单层对象数据结构,做两层浅拷贝即可完全隔离数据:
- 生成
summary数组时,不要只拷贝数组本身,同时对数组内的每个对象做副本创建 - 修正
setSummary的逻辑,不要直接修改传入的原对象,汇总时操作独立的新对象
修正后的业务逻辑代码如下:
const accounts = ref([]) const credits = ref([]) const debits = ref([]) const summary = ref([]) const getaccounts = async () => { try { // getData is a preformatted axios function const response = await getData.get(`/myurl/${route.params.month}/${route.params.year}`) accounts.value = [...response.data.accounts] debits.value = [...response.data.accounts].filter(obj => { return obj.amount < 0 }) // 拷贝数组的同时,为每个对象创建独立副本,切断引用关联 summary.value = debits.value.map(item => ({...item})) setSummary(summary.value) credits.value = [...response.data.comptes].filter(obj => { return obj.amount > 0 }) } catch (error) { console.log(error) } }
修正后的setSummary方法(原代码中resume为笔误,已替换为预先定义的summary,同时避免直接复用原对象):
const setSummary = (debs) => { const arr = debs.reduce((acc, item) => { // 注意字段名和你的实际数据保持一致,原代码中categorie/category拼写需要自行对齐 const existItem = acc.find(({category}) => item.category === category); if(existItem) { existItem.amount += item.amount; } else { // 推入对象副本而非原对象,避免修改原数据 acc.push({ ...item }); } return acc; }, []) summary.value = arr }
说明:以上方案用的是单层对象浅拷贝,性能远高于全量深拷贝,完全适配你的数据结构(对象属性全是number、string这类原始类型)。如果后续数据出现多层嵌套对象/数组,再考虑用原生
structuredClone()方法做深拷贝即可。
内容的提问来源于stack exchange,提问作者thiebo
相关产品推荐
相关产品推荐

