
在 vue 3 中,直接赋值 `submitdata = formdata` 会导致两者共享同一响应式引用,修改副本会意外影响原始数据;正确做法是使用 `toraw()` 获取原始对象,再通过展开运算符创建独立副本,从而彻底隔离响应性。
在 Vue 3(包括 Nuxt 3)中,reactive() 创建的对象是深度响应式的,其内部通过 Proxy 实现依赖追踪。因此,简单赋值(如 submitData = formData)只是复制了响应式代理的引用,而非数据本身——对 submitData 的任何变更(如 delete submitData.key)都会同步反映到 formData 上。
✅ 正确解决方案:先解包,再重建
利用 toRaw() 获取原始非响应式对象,再用 reactive() 创建一个全新的、独立的响应式副本:
import { reactive, toRaw } from 'vue'
const formData = reactive({
name: 'Alice',
email: 'alice@example.com',
token: 'abc123', // 需在提交时移除的敏感字段
agree: true
})
// 创建完全独立的响应式副本
const submitData = reactive({ ...toRaw(formData) })
// 安全删除,仅影响 submitData
delete submitData.token
console.log(formData.token) // 'abc123' —— 未被修改 ✅
console.log(submitData.token) // undefined —— 已被删除 ✅⚠️ 注意事项:
- toRaw() 仅适用于由 reactive()、readonly() 等 Vue 创建的响应式代理对象;对普通对象调用无副作用,但无实际意义。
- 若 formData 包含嵌套响应式对象(如 reactive({ profile: reactive({ ... }) })),toRaw() 会递归解包整个结构,确保深层属性也转为普通 JS 对象,展开后重建的 submitData 是真正独立的深拷贝(浅层响应式,但数据不共享)。
- 不推荐使用 JSON.parse(JSON.stringify()) 做深拷贝:会丢失函数、undefined、Symbol、Date、RegExp 等类型,且无法处理循环引用。
- 若仅需一次性提交且无需后续响应式更新,也可考虑用 toRaw(formData) 直接获取原始对象并操作(此时 submitData 为普通对象,无响应性):
const submitData = { ...toRaw(formData) }
delete submitData.token // 普通对象操作,绝对安全
// 后续提交 API:await $fetch('/api/submit', { method: 'POST', body: submitData })总结:Vue 3 中“停止响应性”并非销毁响应式,而是脱离响应式代理链路。toRaw() 是官方提供的标准解包工具,配合对象展开或结构化克隆,即可在保留所需响应性的同时,实现数据隔离与安全操作。










