Vue 3 中事件透传默认自动实现,无需 $listeners;根元素为普通 HTML 标签时父组件事件自动绑定到其上,也可通过 $attrs 显式透传或解构处理。

Vue 3 中没有 $listeners,因为 v-on="$listeners" 是 Vue 2 的写法。在 Vue 3 里,事件透传更简洁自然——默认就支持,无需手动绑定。
事件自动透传(最常用)
当子组件使用了 <slot></slot>,且父组件在子组件标签上写了事件(如 @click、@submit),只要子组件的根元素是普通 HTML 标签(比如 <div>、<code><button></button>),该事件会**自动透传到根元素上**。
例如:
父组件:
立即学习“前端免费学习笔记(深入)”;
子组件(MyButton.vue):
✅ 点击按钮时,handleClick 会直接触发 —— 不用写任何额外代码。
显式透传事件(需覆盖根元素行为)
如果子组件根节点是组件(如另一个 Vue 组件)、或需要阻止/修改透传逻辑(比如只透传部分事件),可以用 v-on 显式绑定 $attrs 中的事件。
$attrs 在 Vue 3 中默认包含所有未被 props 声明、也未被 v-on 显式声明的事件监听器(如 @change、@input)。
从零开始编排 SpringBoot+Vue 全栈项目工作流,适用于新建全栈项目或完整脚手架请求,触发后依次调用 product‑spec‑builder(需求调研)等模块。
用法示例:
- 透传全部事件:
<childcomponent v-bind="$attrs"></childcomponent> - 透传全部事件 + 额外 props:
<childcomponent v-bind="$attrs" size="large"></childcomponent> - 只透传特定事件(如仅
click和keydown):<div v-on="{ click: $attrs.onClick, keydown: $attrs.onKeydown }"> <p>⚠️ 注意:事件名在 <code>$attrs中是驼峰形式(onClick),对应模板中写的@click;自定义事件同理(@update:modelValue→$attrs['onUpdate:modelValue'])。处理原生事件与自定义事件分离
有时你希望把原生事件(如
@click)绑定到内部某个元素,而把自定义事件(如@change)交给子组件处理。这时可解构$attrs:子组件 script setup:
const { onClick, onChange, ...restAttrs } = $attrs;
defineProps({ /* 显式声明 props */ });模板中:
避免事件重复触发(常见坑)
如果子组件根元素是
<button></button>,又在内部再写一个@click,同时父组件也写了@click,就可能触发两次。解决方法:- 不依赖自动透传,改用显式绑定(
v-on="$attrs"或解构)并统一控制 - 用
.stop修饰符阻止冒泡(仅限 DOM 事件) - 在子组件中通过
defineEmits显式声明要抛出的事件,让调用方更清晰
例如子组件声明:
const emit = defineEmits(['change', 'clear']),然后内部用emit('change')主动触发,而非依赖透传。 - 不依赖自动透传,改用显式绑定(

















