675 字
3 分钟

父组件给子组件标签绑定事件

欢迎来到我的博客!#

使用 Markdown 格式编写。

今天学到了什么#

  • 给组件标签绑事件,实际上是给组件的根节点绑定的,可是在vue3里面,不是不需要加根节点了吗?

这里容易把两件事混在一起:给“组件”绑事件给“DOM 元素”绑事件

1)<MyComp @click="fn" /> 到底绑在哪?#

在 Vue 里,@xxx 有两种含义:

A. 监听“组件自定义事件”(component event)#

这是最标准的理解:父组件在监听子组件 emit('xxx') 出来的事件。

  • 子组件:emit('click')
  • 父组件:<MyComp @click="fn" />

这时候 不是“给子组件根节点绑定 click”,而是“监听子组件发出来的 click 事件”。

在 Vue3 里你用 defineEmits 声明了事件后,@click 会被当成组件事件来处理(不会自动下落到 DOM)。

B. 作为“原生 DOM 事件监听器下落”(fallthrough)#

Vue3 有个机制叫 属性/监听器下落(fallthrough attrs/listeners)

  • 如果你在组件上写了 @click,但子组件并没有把它当成自定义事件(比如没声明 emits: ['click']),那么它可能会被当成一个普通的 listener,自动绑定到子组件的根 DOM 元素上(如果存在单一根节点)。

这就是你听到的那句“给组件标签绑事件,本质是给根节点绑”。

2)那 Vue3 不是可以没有根节点(Fragment)吗?怎么下落?#

对,Vue3 允许组件模板有多个根节点(Fragment)。这会带来一个关键差异:

  • 如果组件只有一个根元素@click 这类监听器可以“自动下落”到这个根元素上。
  • 如果组件有多个根元素(没有单一根):Vue3 不知道该把 listener 绑到哪个元素,所以不会自动绑定,并且会在开发环境给提示(类似 “extraneous non-emits event listeners…”)。

所以结论是:

  • “不需要加根节点”不等于“事件还会自动绑根上”
  • 自动下落只在“单根节点”场景才自然成立

3)实际开发怎么写才不迷糊?#

最稳的做法是分清目的:

我想让父组件接收子组件的动作通知 → 用 emit#

子组件:

const emit = defineEmits<{
(e: 'submit'): void
}>()
emit('submit')

父组件:

<MyComp @submit="fn" />

我想让父组件传进来的 @click 真的绑到子组件某个 DOM 上 → 显式转发 $attrs#

尤其是多根节点组件,推荐你明确指定绑在哪个元素上(不要指望自动下落):

<script setup lang="ts">
defineOptions({ inheritAttrs: false })
</script>
<template>
<button v-bind="$attrs">点我</button>
<div>另一个根</div>
</template>

这样父组件写 <MyComp @click="fn" /> 就会明确绑到那个 button 上。


赞助支持

如果这篇文章对你有帮助,欢迎赞助支持!

赞助
父组件给子组件标签绑定事件
https://firefly.cuteleaf.cn/posts/study-everyday/2026-04-20今日学习-父组件给子组件标签绑定事件/
作者
LJC
发布于
2026-04-20
许可协议
CC BY-NC-SA 4.0
最后更新于 2026-04-20,距今已过 134 天

部分内容可能已过时

目录