Vue如何将子组件所有emit事件透传给父组件?
Vue中子组件所有emit事件批量转发的实现方法
当然有办法实现这种批量监听转发,不用逐个绑定事件,下面分场景给你几种可行方案:
方案一:不修改子组件,直接批量转发(Vue2/Vue3通用)
Vue 2 写法
Vue2 内置了$listeners属性,它包含父组件传递给当前组件的所有事件监听器。如果你的需求是把子组件触发的所有事件直接转发给父组件的上层组件,直接在子组件标签上绑定v-on="$listeners"即可:
<DetailsPages v-if="$route.hash === '#details_pages'" v-on="$listeners" /> <DetailsContact v-if="$route.hash === '#details_contact'" v-on="$listeners" />
这样子组件触发的next、need-to-save等事件,会直接触发父组件的父组件对应的监听器,完全不用逐个绑定。
Vue 3 写法
Vue3 里$listeners被合并到了$attrs中,所以直接用v-on="$attrs"就能实现同样的效果:
<DetailsPages v-if="$route.hash === '#details_pages'" v-on="$attrs" /> <DetailsContact v-if="$route.hash === '#details_contact'" v-on="$attrs" />
方案二:父组件自定义转发逻辑(适合需要额外处理的场景)
如果父组件需要在转发事件前做一些处理,或者只是想把事件转发给自己的上层组件但不想依赖$listeners/$attrs,可以先定义一个通用转发函数,再用对象语法批量绑定:
<script setup> const emit = defineEmits(['next', 'need-to-save', 'goto-step']) // 生成批量转发的事件处理对象 const eventHandlers = ['next', 'need-to-save', 'goto-step'].reduce((handlers, eventName) => { handlers[eventName] = (...args) => emit(eventName, ...args) return handlers }, {}) </script> <template> <DetailsPages v-if="$route.hash === '#details_pages'" v-on="eventHandlers" /> <DetailsContact v-if="$route.hash === '#details_contact'" v-on="eventHandlers" /> </template>
这种写法比逐个绑定简洁很多,而且方便统一修改转发逻辑。
方案三:修改子组件,实现你想要的极简写法
如果你想完全实现类似v-on:emit="$emit"的效果,可以修改子组件,让它接收一个forward函数,把所有原本的emit调用替换成这个函数:
子组件(以DetailsPages.vue为例):
<script setup> // 接收父组件传递的转发函数 const props = defineProps(['forward']) // 原本的事件触发逻辑改成调用forward const handleNext = () => { props.forward('next') } const handleNeedToSave = (save) => { props.forward('need-to-save', save) } const handleGotoStep = (step) => { props.forward('goto-step', step) } </script>
然后父组件就可以用极简方式引用:
<DetailsPages v-if="$route.hash === '#details_pages'" :forward="$emit" /> <DetailsContact v-if="$route.hash === '#details_contact'" :forward="$emit" />
这种写法完全符合你想要的简洁形式,但需要修改所有目标子组件的代码。
内容的提问来源于stack exchange,提问作者Netanel Morali
相关产品推荐
相关产品推荐

