传递复杂初始数据为Props给子组件时,如何正确管理状态?
关于Vue组件间引用传递导致的表单同步问题
这并非严格意义上的Vue问题,而是JavaScript按引用传递特性导致的结果。简而言之,子组件中作为Props传入的对象与父组件中的对象是同一个引用,可直接在子组件中修改它。
场景复现
父组件代码
import NestedForm from "./components/NestedForm.vue"; import { reactive } from "vue"; const formData = reactive({ name: "Some name", ids: [{ number: "ES589348", type: "passport" }], });
这是一个用于编辑包含名称和身份证件数组实体的表单组件,为拆分逻辑,编写子组件处理身份证件编辑部分:
<NestedForm v-model="formData.ids" />
子组件NestedForm代码
const props = defineProps(["modelValue"]); const emit = defineEmits(["update:modelValue"]); const ids = reactive([...props.modelValue]); const addId = () => ids.push({ number: "", type: "" }); const save = () => emit("update:modelValue", ids);
问题分析
- 数组解构仅创建了新数组,但数组内的对象仍与父组件中的对象引用相同(
ids[0] === formData.ids[0]),所以子组件修改对象时无需触发事件就会直接同步到父组件,这违反了Vue建议的组件间通过事件通信的规范。 - 当把响应式Proxy的
ids通过事件传递给父组件后,父组件的formData.ids会与子组件的ids指向同一引用,后续添加新身份证件会立即同步到父组件。
现有解决方案与疑问
目前的解决方式是对传入的Props和输出数据都进行深拷贝,这样子组件内的修改仅在触发事件后同步到父组件,但总觉得这种方式不合理,怀疑是架构设计存在问题或遗漏了某些知识点。
(示例现象:修改第一项内容,父组件立即同步变化(不符合预期,应仅在触发事件后同步);添加新身份证件,暂时无变化,点击保存按钮后,再添加新证件就会与父组件双向绑定)
内容的提问来源于stack exchange,提问作者Kamil Latosinski
相关产品推荐
相关产品推荐

