
在 vue 3 中,直接赋值无法脱离响应式系统;若需对 `reactive` 对象做无副作用的修改(如删除字段而不影响原对象),应先用 `toraw()` 获取原始对象,再通过展开运算符创建独立副本。
在 Nuxt 3 或纯 Vue 3 项目中,当你使用 const formData = reactive({ name: 'Alice', email: 'a@example.com', token: 'xxx' }) 定义表单数据时,该对象及其所有嵌套属性均被 Proxy 包裹,具备响应式能力。此时若执行 submitData = formData,实际只是复制了响应式代理的引用——submitData 和 formData 指向同一响应式对象,因此 delete submitData.token 会同步反映到 formData 上,违背预期。
✅ 正确做法是:剥离响应式代理,再构造新响应式对象。Vue 提供了 toRaw() 工具函数,用于安全获取被 reactive()、ref() 等包裹的原始对象(非 Proxy 版本)。配合对象展开语法,即可生成一份与原对象结构一致、但完全独立的副本:
import { reactive, toRaw } from 'vue'
const formData = reactive({
name: 'Alice',
email: 'a@example.com',
token: 'abc123',
createdAt: new Date()
})
// 创建独立的、可自由修改的 reactive 副本
const submitData = reactive({ ...toRaw(formData) })
// ✅ 安全删除,不影响 formData
delete submitData.token
delete submitData.createdAt
console.log(formData.token) // 'abc123' —— 未被删除
console.log(submitData.token) // undefined —— 已删除⚠️ 注意事项:
- toRaw() 仅对由 Vue 创建的响应式对象有效;对普通对象调用无副作用,但无必要;
- 若 formData 含深层嵌套对象或数组,{ ...toRaw(formData) } 仅执行浅拷贝,嵌套属性仍可能共享引用(如 formData.profile = reactive({ age: 30 }))。此时建议结合 structuredClone()(现代浏览器支持)或 lodash.cloneDeep() 进行深拷贝后再 reactive();
- 不推荐在模板中频繁调用 toRaw(),它属于底层工具,应仅用于逻辑隔离场景(如提交前清洗数据);
- 替代方案:若无需保留响应式,也可直接使用 const submitData = { ...toRaw(formData) }(非 reactive),适用于一次性提交场景。
总结:toRaw() 是 Vue 3 提供的关键“脱敏”工具,配合解构赋值可高效实现响应式对象的隔离拷贝。在表单提交、API 请求载荷构建等需要临时修改数据又不污染源状态的场景中,这是简洁、可靠且符合 Vue 哲学的标准实践。
立即学习“前端免费学习笔记(深入)”;










