You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 00:51:27