此章节假设你已经看过了组件基础。若你还不了解组件是什么,请先阅读该章节。
触发与监听事件
在组件的模板表达式中,可以直接使用 $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。