在 Vue 3 中,当子组件需要修改父组件传递的数据副本并同步更新时,可以通过以下步骤实现:
方法 1:使用 v-model
和计算属性(实时同步)
父组件:
vue
<template>
<ChildComponent v-model="parentData" />
</template>
<script setup>
import { ref } from 'vue';
const parentData = ref(initialValue);
</script>
子组件:
vue
<template>
<input v-model="modelValueComputed" />
</template>
<script setup>
import { computed } from 'vue';
const props = defineProps(['modelValue']);
const emit = defineEmits(['update:modelValue']);
// 计算属性实现双向绑定
const modelValueComputed = computed({
get: () => props.modelValue,
set: (value) => emit('update:modelValue', value)
});
</script>
方法 2:使用副本和侦听器(实时同步)
父组件同上。
子组件:
vue
<template>
<input v-model="localData" />
</template>
<script setup>
import { ref, watch } from 'vue';
const props = defineProps(['modelValue']);
const emit = defineEmits(['update:modelValue']);
// 创建副本
const localData = ref(props.modelValue);
// 监听本地副本变化,同步到父组件
watch(localData, (newVal) => {
emit('update:modelValue', newVal);
});
// 监听父组件数据变化,更新副本
watch(() => props.modelValue, (newVal) => {
localData.value = newVal;
});
</script>
方法 3:手动触发更新(如提交按钮)
父组件:
vue
<template>
<ChildComponent :data="parentData" @update="handleUpdate" />
</template>
<script setup>
import { ref } from 'vue';
const parentData = ref(initialValue);
const handleUpdate = (newVal) => {
parentData.value = newVal;
};
</script>
子组件:
vue
<template>
<input v-model="localData" />
<button @click="submit">提交</button>
</template>
<script setup>
import { ref, watch } from 'vue';
const props = defineProps(['data']);
const emit = defineEmits(['update']);
// 初始化副本
const localData = ref(props.data);
// 父组件数据变化时更新副本
watch(() => props.data, (newVal) => {
localData.value = newVal;
});
const submit = () => {
emit('update', localData.value);
};
</script>
关键点说明:
-
副本创建 :子组件通过
ref
或reactive
创建数据的副本,避免直接修改 Props。 -
数据同步:
-
实时同步 :通过
watch
监听副本变化并触发事件 (emit
),同时监听 Props 更新副本。 -
手动同步:在用户操作(如点击按钮)时提交修改。
-
-
双向绑定 :利用
v-model
语法糖简化父子通信,自动处理 Prop 和事件。 -
更新策略:根据场景选择是否实时同步或手动同步,避免循环更新或数据不一致。
注意事项:
-
深拷贝 :如果传递的是对象/数组,需使用深拷贝(如
JSON.parse(JSON.stringify(props.data))
)避免引用问题。 -
性能 :频繁的
watch
可能影响性能,复杂场景可考虑防抖或优化监听逻辑。 -
数据一致性:父组件更新后,若需子组件副本同步,务必监听 Prop 变化并更新副本。