Vue深拷贝核心是“复制后能否安全用”,需先toRaw解包再拷贝,编辑后按需用ref/reactive重包装;特殊类型须用lodash.cloneDeep或fast-copy,跨组件编辑必须切断引用链。

Vue.js 处理复杂对象深拷贝,核心不是“怎么复制”,而是“复制后能否安全用”——既要脱离响应式代理干扰,又要保证数据结构完整、编辑不污染源、回传能恢复响应性。
先解包,再拷贝,最后按需重包装
ref 或 reactive 包裹的对象不能直接深拷贝。Proxy 代理对象无法被 structuredClone 克隆,JSON 方法会丢 Date、RegExp、undefined 和函数,递归实现若没处理 toRaw 就可能触发响应式副作用。
- 对 ref:取
.value得到原始值,再拷贝 - 对 reactive:用
toRaw()解包,避免 Proxy 干扰 - 拷贝后若需响应式:用
ref()或reactive()包一层 - 若只是临时编辑(如表单暂存),返回普通对象即可,无需重包装
选对拷贝方式,匹配数据特征
没有万能方案,得看数据里有没有特殊类型、是否高频操作、是否要兼容老环境。
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
- 纯 JSON 结构(无函数、Date、undefined、循环引用)→
JSON.parse(JSON.stringify(obj)) - 含 Date / RegExp / Map / Set / 循环引用 → 推荐
lodash.cloneDeep或fast-copy - 性能敏感场景(如画布快照、高频配置切换)→
fast-copy比 lodash 更轻更快 - 需定制逻辑(跳过某些字段、替换值、过滤 Symbol 键)→ 手写递归 +
toRaw+WeakMap防循环
跨组件编辑时,必须隔离源数据
父组件传 reactive 对象给子组件,子组件直接改会污染源;用浅拷贝又容易深层联动。正确路径是切断引用链。
立即学习“前端免费学习笔记(深入)”;
- 子组件接收后,立刻
const raw = toRaw(props.data) - 用合适方式深拷贝出一份干净副本
- 所有本地编辑都在副本上进行(支持撤销、对比、重置)
- 提交时,再把编辑结果
reactive()包装或通过 emit 传回
动态结构与特殊类型,绕开 reactive 陷阱
Map、Set、类实例、递归嵌套表单等,硬套 reactive 容易卡顿或行为异常。
-
Map / Set:统一用
ref(new Map()),遍历时调用.value.entries() -
类实例:必须
ref(markRaw(new MyClass())),防止 Proxy 干预方法和私有字段 -
大型嵌套结构(如组织树、动态字段组):顶层用
shallowReactive,子节点用普通对象或markRaw - 条件显隐的表单:按区块拆分,每个区块用独立 ref 管理,避免全量 reactive 带来的依赖风暴

















