此章节假设你已经看过了组件基础。若你还不了解组件是什么,请先阅读该章节。
触发与监听事件
在组件的模板表达式中,可以直接使用 $emit 方法触发自定义事件 (例如:在 v-on 的处理函数中):
<!-- MyComponent --><button @click="$emit('someEvent')">click me</button>
父组件可以通过 v-on (缩写为 @) 来监听事件:
<MyComponent @some-event="callback" />
同样,组件的事件监听器也支持 .once 修饰符:
<MyComponent @some-event.once="callback" />
像组件与 prop 一样,事件的名字也提供了自动的格式转换。注意这里我们触发了一个以 camelCase 形式命名的事件,但在父组件中可以使用 kebab-case 形式来监听。与 prop 大小写格式一样,在模板中我们也推荐使用 kebab-case 形式来编写监听器。
:::success
TIP
和原生 DOM 事件不一样,组件触发的事件没有冒泡机制。你只能监听直接子组件触发的事件。平级组件或是跨越多层嵌套的组件间通信,应使用一个外部的事件总线,或是使用一个全局状态管理方案。
:::
事件
<!-- A.vue --><script setup>import B from "./B.vue"function callback() {console.log('trigger some-event')}</script><template><B @some-event="callback" /></template>
<!-- B.vue --><template><button @click="$emit('someEvent')">click me</button></template>


每次点击按钮,都会触发 callback。
.once 修饰符
<!-- A.vue --><script setup>import B from "./B.vue"function callback() {console.log('trigger some-event')}</script><template><B @some-event.once="callback" /></template>
<!-- B.vue --><template><button @click="$emit('someEvent')">click me</button></template>
如果加上 .once 修饰符,那么 callback 仅会触发一次。
无冒泡机制
<!-- A.vue --><script setup>import { ref } from "vue";import B from "./B.vue";const message = ref("未收到事件");function callback() {message.value = "收到事件";}</script><template><B @someEvent="callback" /><div>父组件: {{ message }}</div></template>
<!-- B.vue --><script setup>import { ref } from "vue";import C from "./C.vue";const message = ref("未收到事件");function callback() {message.value = "收到事件";}defineEmits(["someEvent"]);</script><template><C @someEvent="callback" /><div>子组件: {{ message }}</div></template>
<!-- C.vue --><script setup>defineEmits(["someEvent"]);</script><template><button @click="$emit('someEvent')">孙组件: Click me</button></template>
按钮点击之前:
按钮点击之后:
C 组件的事件只会传递到直接父组件 B,并不会继续往上冒泡到祖先组件 A。
