Vue中重置指向ref嵌套属性的v-model为何直接赋值initState无效?
如何重置ref并更新指向其嵌套属性的v-model?
问题原因分析
你遇到的问题核心是对象引用的复用:
当执行const form = ref(initState)时,form.value和initState指向的是同一块内存地址的对象。后续通过v-model修改form.text.value时,实际上是直接修改了initState对象内部的属性值。
所以当你尝试用form.value = initState重置时,本质是把同一个对象引用重新赋值给ref,Vue的响应式系统无法检测到引用变化(因为前后指向的是同一个对象),因此不会触发视图更新。
而手动创建新对象{ text: { value: "", isDirty: false } }时,这个对象是全新的内存引用,Vue能检测到form.value的引用变化,从而触发视图更新。
解决方法
方法1:对initState进行深拷贝
每次重置时生成一个与initState结构完全相同的新对象,避免引用复用:
const initState = { text: { value: "", isDirty: false, }, }; const form = ref(initState); const reset = () => { // 通过JSON序列化/反序列化实现深拷贝(适合无复杂类型的对象) form.value = JSON.parse(JSON.stringify(initState)); };
方法2:用工厂函数生成初始状态
把初始状态封装成函数,每次调用都返回新对象:
// 工厂函数,每次调用返回全新的初始对象 const getInitState = () => ({ text: { value: "", isDirty: false, }, }); const form = ref(getInitState()); const reset = () => { form.value = getInitState(); };
方法3:结合Vue响应式API优化(推荐)
如果使用Vue 3的Composition API,也可以用reactive管理状态,重置时直接替换属性更直观:
const initState = { text: { value: "", isDirty: false, }, }; const form = reactive({ ...initState }); const reset = () => { // 直接替换整个text对象 form.text = { ...initState.text }; // 或者逐个重置属性 // form.text.value = initState.text.value; // form.text.isDirty = initState.text.isDirty; };
原始代码整理
组件脚本:
const initState = { text: { value: "", isDirty: false, }, }; const form = ref(initState); const reset = () => { // 无效:引用未变化 // form.value = initState; // 有效:新对象引用 form.value = { text: { value: "", isDirty: false, }, }; };
模板:
<template> <form> <input v-model="form.text.value" placeholder="enter text..." /> <button @click.prevent="reset">reset</button> </form> <div>{{ form.text.value }}</div> </template>
内容的提问来源于stack exchange,提问作者Thanh Hải Nguyễn Huỳnh
相关产品推荐
相关产品推荐

