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

Vue组件中深度克隆对象报DataCloneError,疑与Promise相关

问题原因及解决方案

核心问题

  1. 异步执行顺序错误:你当前的this.cloneEmployees = structuredClone(this.employees)写在fetch回调外部,属于同步执行逻辑,此时this.employees还是初始空数组,根本没拿到接口返回的数据。即便你尝试把克隆代码放到then里,也会因为this.employees是Vue响应式对象——内部包含Vue注入的观察者属性(如__ob__),这类属性无法被structuredClone或JSON.parse(JSON.stringify)序列化,从而抛出DataCloneError。
  2. 响应式对象无法直接克隆:Vue2通过Object.defineProperty给数据添加响应式拦截,生成的响应式对象带有不可序列化的内部属性,直接克隆会触发序列化错误。

解决方案

方案1:先处理原始数据,再分别赋值给响应式变量

先基于接口返回的原始数据生成非响应式的处理结果,再分别赋值给this.employees和this.cloneEmployees,避免克隆响应式对象:

<script>
export default {
  data() {
    return {
      employees: [],
      cloneEmployees: [],
    };
  },
  mounted() {
    fetch("http://localhost:3000/employees")
      .then((response) => response.json())
      .then((response) => {
        // 先处理原始数据,得到非响应式数组
        const rawEmployees = response.map((e) => ({
          ...e,
          subjects: e.subjects.split(",")
        }));
        // 分别赋值给响应式变量,克隆操作针对原始数据
        this.employees = rawEmployees;
        this.cloneEmployees = JSON.parse(JSON.stringify(rawEmployees));
        // 也可以用structuredClone克隆原始数据
        // this.cloneEmployees = structuredClone(rawEmployees);
      });
  }
};
</script>

方案2:获取原始数据后再克隆(Vue2专用)

如果要基于this.employees克隆,可以通过Vue.util.toRaw获取其对应的非响应式原始对象,再执行克隆:

import Vue from 'vue';

export default {
  // ...其他代码
  mounted() {
    fetch("http://localhost:3000/employees")
      .then((response) => response.json())
      .then((response) => {
        this.employees = response.map((e) => ({
          ...e,
          subjects: e.subjects.split(",")
        }));
        // 获取原始非响应式数据后克隆
        this.cloneEmployees = JSON.parse(JSON.stringify(Vue.util.toRaw(this.employees)));
      });
  }
};

方案3:自定义深克隆函数

如果担心内置API的局限性,可以自己实现一个仅克隆普通可枚举属性的深克隆函数:

function deepClone(obj) {
  if (obj === null || typeof obj !== 'object') return obj;
  if (Array.isArray(obj)) return obj.map(item => deepClone(item));
  const clonedObj = {};
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      clonedObj[key] = deepClone(obj[key]);
    }
  }
  return clonedObj;
}

// 在then回调中使用
this.cloneEmployees = deepClone(rawEmployees);

验证要点

  • 克隆操作必须放在fetch的then回调内部,确保接口数据已处理完成
  • 克隆的目标必须是非响应式的原始数据,而非Vue包装后的响应式对象

内容的提问来源于stack exchange,提问作者JJJ

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 10:22:32