原文 👉 组件事件 | Vue.js

此章节假设你已经看过了组件基础。若你还不了解组件是什么,请先阅读该章节。

触发与监听事件

在组件的模板表达式中,可以直接使用 $emit 方法触发自定义事件 (例如:在 v-on 的处理函数中):

  1. <!-- MyComponent -->
  2. <button @click="$emit('someEvent')">click me</button>

父组件可以通过 v-on (缩写为 @) 来监听事件:

  1. <MyComponent @some-event="callback" />

同样,组件的事件监听器也支持 .once 修饰符:

  1. <MyComponent @some-event.once="callback" />

像组件与 prop 一样,事件的名字也提供了自动的格式转换。注意这里我们触发了一个以 camelCase 形式命名的事件,但在父组件中可以使用 kebab-case 形式来监听。与 prop 大小写格式一样,在模板中我们也推荐使用 kebab-case 形式来编写监听器。

:::success TIP
和原生 DOM 事件不一样,组件触发的事件没有冒泡机制。你只能监听直接子组件触发的事件。平级组件或是跨越多层嵌套的组件间通信,应使用一个外部的事件总线,或是使用一个全局状态管理方案。 :::

事件

  1. <!-- A.vue -->
  2. <script setup>
  3. import B from "./B.vue"
  4. function callback() {
  5. console.log('trigger some-event')
  6. }
  7. </script>
  8. <template>
  9. <B @some-event="callback" />
  10. </template>
  1. <!-- B.vue -->
  2. <template>
  3. <button @click="$emit('someEvent')">click me</button>
  4. </template>

image.png

image.png

每次点击按钮,都会触发 callback。

.once 修饰符

  1. <!-- A.vue -->
  2. <script setup>
  3. import B from "./B.vue"
  4. function callback() {
  5. console.log('trigger some-event')
  6. }
  7. </script>
  8. <template>
  9. <B @some-event.once="callback" />
  10. </template>
  1. <!-- B.vue -->
  2. <template>
  3. <button @click="$emit('someEvent')">click me</button>
  4. </template>

如果加上 .once 修饰符,那么 callback 仅会触发一次。

无冒泡机制

  1. <!-- A.vue -->
  2. <script setup>
  3. import { ref } from "vue";
  4. import B from "./B.vue";
  5. const message = ref("未收到事件");
  6. function callback() {
  7. message.value = "收到事件";
  8. }
  9. </script>
  10. <template>
  11. <B @someEvent="callback" />
  12. <div>父组件: {{ message }}</div>
  13. </template>
  1. <!-- B.vue -->
  2. <script setup>
  3. import { ref } from "vue";
  4. import C from "./C.vue";
  5. const message = ref("未收到事件");
  6. function callback() {
  7. message.value = "收到事件";
  8. }
  9. defineEmits(["someEvent"]);
  10. </script>
  11. <template>
  12. <C @someEvent="callback" />
  13. <div>子组件: {{ message }}</div>
  14. </template>
  1. <!-- C.vue -->
  2. <script setup>
  3. defineEmits(["someEvent"]);
  4. </script>
  5. <template>
  6. <button @click="$emit('someEvent')">孙组件: Click me</button>
  7. </template>

按钮点击之前:
image.png

按钮点击之后:
image.png

C 组件的事件只会传递到直接父组件 B,并不会继续往上冒泡到祖先组件 A。

事件参数

声明触发的事件

事件校验