Vue3组合式API使用Object.assign重置嵌套属性表单失效如何解决
问题根因
Object.assign是浅拷贝逻辑,仅会覆盖对象的顶层属性,碰到属性值为引用类型(例如你代码中的details对象)时,只会拷贝引用地址,不会递归处理深层属性。- 你初始化
form时用的展开运算符{ ...initialForm }也属于浅拷贝,此时form.details和initialForm.details指向同一块内存空间,后续修改form.details.type时,initialForm.details.type也会被同步修改,就算执行Object.assign也拿不到最初的初始值。
可行的重置方案
方案1:深拷贝初始值 + 重置
如果你能接受引入深拷贝能力,是通用性最高的方案:
- 可以用第三方库的深拷贝方法(比如lodash的
cloneDeep),也可以用浏览器原生的structuredClone方法(无需引入依赖,兼容性覆盖绝大多数现代业务场景) - 初始化和重置时都对初始模板做深拷贝,切断引用关联
import { reactive } from 'vue' // 用原生structuredClone的话不需要引入第三方包 // import { cloneDeep } from 'lodash-es' const initialForm = { name: "", details: { type: "" } }; // 初始化时深拷贝,避免和初始模板引用关联 const form = reactive(structuredClone(initialForm)); const resetForm = () => { // 重置时重新深拷贝初始模板,覆盖所有属性 Object.assign(form, structuredClone(initialForm)) }
你也可以把表单包在reactive的一个顶层属性里,重置时直接替换整个表单对象,写法更简单:
const state = reactive({ form: structuredClone(initialForm) }) const resetForm = () => { state.form = structuredClone(initialForm) }
方案2:用ref定义表单,直接替换值
用ref包裹表单对象的话,可以直接给ref.value赋值新对象,不需要用Object.assign:
import { ref } from 'vue' const initialForm = { name: "", details: { type: "" } }; const form = ref(structuredClone(initialForm)); const resetForm = () => { form.value = structuredClone(initialForm) }
方案3:分层手动重置(适合表单结构简单的场景)
如果你的表单嵌套层级少、结构固定,可以手动分层赋值,不需要深拷贝:
const resetForm = () => { form.name = initialForm.name // 直接替换整个details对象 form.details = { ...initialForm.details } }
内容的提问来源于stack exchange,提问作者ScriptMint Solution
相关产品推荐
相关产品推荐

