You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 23:08:29