Vue3嵌套组件多按钮Emit失效问题及正确实现方法
问题原因
核心问题是中间组件ButtonsList没有转发子组件的自定义事件。当ButtonsList只放一个按钮时,Vue的事件冒泡机制可能偶然让HelloWorld组件接收到了子按钮的emit事件;但放入两个按钮后,这种偶然的传递被打断,HelloWorld根本收不到ButtonPlus/ButtonMinus触发的事件,导致功能完全失效。
解决方案
不需要采用React式传函数,用Vue的事件转发或透传即可解决,以下是两种可行方式:
方式一:显式转发事件(推荐,逻辑清晰)
修改ButtonsList组件,监听子按钮的事件后转发给父组件:
<script setup> import ButtonPlus from '../Buttons/ButtonPlus.vue' import ButtonMinus from '../Buttons/ButtonMinus.vue' // 声明要转发的事件 const emit = defineEmits(['update:plusEmit', 'update:minusEmit']) </script> <template> <ButtonPlus @update:plusEmit="() => emit('update:plusEmit')"/> <ButtonMinus @update:minusEmit="() => emit('update:minusEmit')"/> </template>
同时建议子组件显式声明emit事件(规范写法,避免隐式事件):
ButtonPlus.vue:
<script setup> // 显式声明要触发的事件 const emit = defineEmits(['update:plusEmit']) const plus = () => { emit('update:plusEmit') } </script> <template> <button @click="plus">+</button> </template>
ButtonMinus.vue:
<script setup> const emit = defineEmits(['update:minusEmit']) const minus = () => { emit('update:minusEmit') } </script> <template> <button @click="minus">-</button> </template>
方式二:使用$attrs透传事件
如果不想显式转发,可以让ButtonsList透传父组件绑定的事件给子组件:
<script setup> import ButtonPlus from '../Buttons/ButtonPlus.vue' import ButtonMinus from '../Buttons/ButtonMinus.vue' </script> <template> <ButtonPlus v-bind="$attrs"/> <ButtonMinus v-bind="$attrs"/> </template>
这种方式下,HelloWorld绑定的@update:plusEmit和@update:minusEmit会直接传递给对应的子按钮组件,需保证子组件的事件名和父组件绑定的一致。
内容的提问来源于stack exchange,提问作者Akira
相关产品推荐
相关产品推荐

