vue3 emit(保姆级教程)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观

前言

在 Vue.js 的开发中,组件之间的通信是构建复杂应用的核心能力之一。Vue3 emit 作为 Vue3 中实现组件间事件通信的关键机制,为开发者提供了一种灵活且直观的方式,尤其在父子组件协作场景中发挥重要作用。本文将从基础概念到高级技巧,结合代码示例和实际案例,系统讲解 Vue3 emit 的使用方法,并通过比喻和分步解析,帮助读者快速掌握这一核心知识点。


核心概念解析:事件驱动与父子通信

在 Vue3 中,emitthis.$emit 方法的延续,用于在组件内部触发自定义事件。其核心逻辑基于事件驱动模型:

  • 事件触发者(通常为子组件)通过 emit 方法向外部发出信号;
  • 事件监听者(通常为父组件)通过 v-on@ 语法监听并响应事件。

这一机制可以类比为快递服务:

  • 子组件(寄件人)通过 emit 发送包裹(事件);
  • 父组件(收件人)通过 v-on 接收包裹,并处理包裹中的内容(事件参数)。

知识点:事件触发与监听的双向协作

父子组件的通信需要满足两个条件:

  1. 子组件定义事件:通过 emit 方法明确事件名称及携带的数据;
  2. 父组件监听事件:通过 v-on 绑定事件名称,并编写响应逻辑。

基础用法:父子组件通信的典型场景

示例 1:父组件监听子组件事件

<!-- ParentComponent.vue -->
<template>
  <ChildComponent @custom-event="handleChildEvent" />
</template>

<script>
export default {
  methods: {
    handleChildEvent(data) {
      console.log("父组件收到子组件的事件:", data);
    },
  },
};
</script>
<!-- ChildComponent.vue -->
<script>
export default {
  methods: {
    triggerEvent() {
      this.$emit("custom-event", { message: "Hello from child!" });
    },
  },
};
</script>

解析

  • 子组件通过 this.$emit("custom-event", data) 触发事件;
  • 父组件通过 @custom-event="handleChildEvent" 监听事件,并执行回调函数处理数据。

进阶技巧:事件参数传递与命名规范

技巧 1:传递复杂数据类型

事件不仅支持传递简单值(如字符串、数字),还可携带对象或数组:

<!-- ChildComponent.vue -->
methods: {
  sendData() {
    const payload = {
      id: 123,
      details: ["detail1", "detail2"],
    };
    this.$emit("data-sent", payload);
  },
},

父组件可通过解构参数直接使用数据:

handleDataSent({ id, details }) {
  console.log("ID:", id);        // 输出 123
  console.log("Details:", details); // 输出数组
}

技巧 2:事件命名规范

为提高代码可维护性,建议遵循以下命名规则:

  • 驼峰命名法:如 user-selecteduserSelected
  • 短横线命名法:Vue 推荐在模板中使用短横线(如 @user-selected),在代码中使用驼峰(如 $emit("user-selected"))。

组合式 API 中的 emit 实现

Vue3 的组合式 API(Composition API)通过 defineEmits 函数显式定义事件,进一步提升类型安全:

<script setup>
const emit = defineEmits(["form-submitted"]);

const handleSubmit = (formData) => {
  emit("form-submitted", formData);
};
</script>

优势对比
| 选项式 API | 组合式 API |
|---------------------------|-------------------------------|
| 通过 this.$emit 触发事件 | 通过 emit 函数触发事件 |
| 事件需在 emits 选项中声明 | 通过 defineEmits 显式定义事件 |


高级场景:事件总线与跨级通信

场景 1:跨组件通信的事件总线方案

当需要非父子组件通信时,可通过 Vue3 的 provide/inject 或第三方工具(如 mitt)创建事件总线:

// eventBus.js
import { mitt } from "mitt";
export const emitter = mitt();
<!-- 组件A.vue -->
<script setup>
import { emitter } from "./eventBus.js";

const triggerGlobalEvent = () => {
  emitter.emit("global-event", "触发全局事件!");
};
</script>
<!-- 组件B.vue -->
<script setup>
import { emitter } from "./eventBus.js";

emitter.on("global-event", (data) => {
  console.log("组件B收到全局事件:", data);
});
</script>

场景 2:事件修饰符的灵活应用

Vue 支持事件修饰符(如 .once.stop),可简化逻辑:

<!-- 仅触发一次事件 -->
<ChildComponent @custom-event.once="handleOnce" />

<!-- 阻止事件冒泡 -->
<ChildComponent @custom-event.stop="handleStop" />

常见问题与解决方案

问题 1:事件未触发或未被监听

可能原因

  • 父组件未正确绑定事件名称(如 @custom-event 写成 @customEvent);
  • 子组件未定义事件(未调用 this.$emit)。

解决方案

  1. 检查事件名称的大小写一致性;
  2. 在子组件中添加调试 console.log 验证事件触发。

问题 2:事件参数传递错误

常见错误

  • 父组件未正确解构参数(如将对象参数写成 handleEvent(id) 而非 handleEvent({ id }))。

解决方案

  • 在父组件中通过 console.log 输出参数,确认数据结构;
  • 使用 TypeScript 类型注解增强类型检查。

结论

通过本文的讲解,读者应已掌握 Vue3 emit 的核心原理、基础用法及高级技巧。无论是父子组件的直接通信,还是通过事件总线实现跨组件协作,emit 都是构建复杂 Vue 应用的基石。建议读者通过以下步骤实践巩固知识:

  1. 编写一个包含父子组件的简单计数器应用,通过 emit 传递数值;
  2. 尝试使用组合式 API 重构现有项目,体验 defineEmits 的优势;
  3. 探索 mitt 库,实现全局状态管理的轻量级方案。

掌握 Vue3 emit 不仅能提升代码的可维护性,更能帮助开发者构建更灵活、可扩展的前端架构。

最新发布