Vue嵌套组件双向绑定复用触发prop意外突变报错该如何解决?
问题原因
- Vue遵循单向数据流规则,禁止子组件直接修改传入的prop值。你在Contact组件中直接给Mother组件的
v-model:mother绑定了contact.mother,v-model的默认实现会直接修改绑定的原始值,也就是修改了属于prop的contact对象的属性,因此触发了vue/no-mutating-props的ESLint校验报错。
修复方案
修改Contact组件的实现,把透传给Mother组件的v-model拆分为手动属性绑定和事件监听,所有变更都通过emit通知上层组件更新,避免直接修改prop:
<!-- Contact.vue 模板部分修改 --> <template> <div> <input :value="contact.firstName" @input="$emit('update:contact', {...contact, firstName: $event.target.value})"> <!-- 拆分v-model为单独的props绑定和事件监听 --> <Mother :mother="contact.mother" @update:mother="handleMotherUpdate"/> </div> </template> <script> import Mother from '@/components/Mother' export default { name: 'Contact', components: { Mother }, props: { contact: Object, }, emit: ['update:contact'], methods: { handleMotherUpdate(newMotherVal) { // 构造新的contact对象向上emit,不修改原有prop this.$emit('update:contact', { ...this.contact, mother: newMotherVal }) } } } </script>
修改完成后,Mother组件的变更会先传递到Contact组件,Contact组件再构造完整的新contact对象通知上层父组件更新,完全符合单向数据流的要求,不会再触发prop突变报错,同时也支持同一页面多Contact组件实例独立使用的需求。
如果你使用Vue3的setup语法,还可以用computed的get/set简化写法,无需手动编写事件监听方法:
<!-- Vue3 setup语法糖可选方案 --> <script setup> import { computed } from 'vue' import Mother from '@/components/Mother' const props = defineProps(['contact']) const emit = defineEmits(['update:contact']) const contactModel = computed({ get() { return props.contact }, set(newVal) { emit('update:contact', newVal) } }) </script> <template> <div> <input v-model="contactModel.firstName" /> <Mother v-model:mother="contactModel.mother" /> </div> </template>
内容的提问来源于stack exchange,提问作者Ace of Spade
相关产品推荐
相关产品推荐

