如何让两个子组件同步更新同一个父组件属性?
问题描述
需要用复选框按类别过滤产品,创建父组件传递类别选项给子组件并维护选中状态。单个子组件运行正常,但添加第二个相同子组件(比如常规菜单和移动端菜单各一个)时,选中状态无法同步:在第一个子组件选类别“A”,第二个子组件的“A”复选框不会勾选。期望绑定同一个v-model实现同步,如何确保修改一个子组件时父组件更新且另一子组件状态同步?
父组件代码(Parent.vue)
<template> <FilterCheckboxItem ref="Category" name="Category" :FilterOptions="CategoryOptions" v-model="FilteredCategories" /> <!-- 第二个子组件,绑定同一个v-model --> <FilterCheckboxItem ref="MobileCategory" name="MobileCategory" :FilterOptions="CategoryOptions" v-model="FilteredCategories" /> </template> <script> export default { data(){ return { FilteredCategories: [], CategoryOptions: ["A","B","C"] } } </script>
原小子组件代码(FilterCheckboxItem.vue)
<template> <div v-for="FilterOption in FilterOptions" > <input type="checkbox" :value="FilterOption" v-model="checked" /> </div> </template> <script> export default { props: { FilterOptions: { type: Array, }, modelValue: { type: Array, }, }, emits: ['update:modelValue'], setup(props, { emit }) { const checked = ref([]); watch(checked, (newVal) => { emit('update:modelValue', newVal); }); return { emit, checked }; }, </script>
解决方案
问题出在子组件内部的checked变量没有和父组件传递的modelValue做双向同步:子组件只监听了自身checked的变化并通知父组件,但没有监听父组件modelValue的变化来更新自身的checked状态。
修改后的子组件代码如下:
<template> <div v-for="FilterOption in FilterOptions" :key="FilterOption" <!-- 添加key避免渲染问题 --> > <input type="checkbox" :value="FilterOption" v-model="checked" /> </div> </template> <script> import { ref, watch } from 'vue'; export default { props: { FilterOptions: { type: Array, required: true }, modelValue: { type: Array, default: () => [] }, }, emits: ['update:modelValue'], setup(props, { emit }) { const checked = ref([...props.modelValue]); // 初始化时同步父组件值 // 监听自身checked变化,通知父组件 watch(checked, (newVal) => { emit('update:modelValue', [...newVal]); // 传递新数组避免引用问题 }, { deep: true }); // 监听父组件modelValue变化,更新自身checked watch(() => props.modelValue, (newVal) => { checked.value = [...newVal]; }, { deep: true }); return { checked }; }, }; </script>
关键修改点说明
- 初始化同步:子组件的
checked变量初始化时直接使用父组件传递的modelValue值,确保初始状态和父组件一致。 - 监听父组件值变化:添加对
props.modelValue的监听,当父组件的选中状态更新(比如另一个子组件修改后),立即同步更新自身的checked状态。 - 添加
deep: true:因为监听的是数组类型,需要开启深度监听才能捕获数组内部元素的变化。 - 传递新数组:在通知父组件时,传递数组的副本(
[...newVal]),避免因为引用类型导致的意外问题。 - 添加v-for的key:为循环的复选框元素添加唯一key,确保Vue正确追踪DOM元素,避免渲染异常。
这样修改后,两个子组件绑定同一个父组件的FilteredCategories,任意一个子组件修改选中状态,都会通过v-model同步到父组件,另一个子组件会监听父组件的变化自动更新自身的复选框状态,实现双向同步。
内容的提问来源于stack exchange,提问作者Jason
相关产品推荐
相关产品推荐

