当前位置: 首页 > news >正文

Vue 3 中的事件总线

在 Vue 3 中,由于创建 Vue 实例的方式发生了变化,并且推荐使用 Composition API,事件总线的实现方式也与 Vue 2 有所不同。


一、Vue 3 事件总线的核心变化

在 Vue 2 中,我们通常 new Vue() 来创建事件总线。但在 Vue 3 中:

  1. Vue 构造函数不再直接导出,取而代之的是 createApp
  2. Vue 实例不再是一个事件发射器,它移除了 $on, $off, 和 $once 方法。

因此,我们不能再用 new Vue() 来创建事件总线


二、Vue 3 实现事件总线的推荐方案

有几种方式可以在 Vue 3 中实现事件总线模式,这里介绍最主流和推荐的两种。

方案一:使用第三方库 mitt(最推荐)

mitt 是一个小巧(约 200 bytes)、功能完整的的事件总线库,它不依赖 Vue,但可以完美地与 Vue 3 集成。这是目前 Vue 社区公认的最佳实践。

1. 安装 mitt

npm install mitt

2. 创建事件总线
创建一个单独的文件(如 event-bus.js):

// event-bus.js
import mitt from 'mitt';// 创建一个 mitt 实例并导出
const emitter = mitt();export default emitter;

3. 在组件中使用

发布事件(发送消息):
使用 emitter.emit(eventType, data)

<!-- PublisherComponent.vue -->
<template><button @click="sendMessage">发送消息</button>
</template><script setup>
import { ref } from 'vue';
import emitter from './event-bus.js'; // 导入事件总线const message = ref('Hello from Vue 3!');const sendMessage = () => {// 发布一个名为 'messageEvent' 的事件,并携带数据emitter.emit('messageEvent', message.value);// 也可以发布没有数据的事件// emitter.emit('someNotification');
};
</script>

订阅事件(接收消息):
使用 emitter.on(eventType, callback)
关键点: 在 Composition API 的 setup 中,需要在 onMounted 生命周期中订阅,并在 onUnmounted 中取消订阅,以防止内存泄漏。

<!-- SubscriberComponent.vue -->
<template><div>收到消息: {{ receivedMessage }}</div>
</template><script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import emitter from './event-bus.js'; // 导入事件总线const receivedMessage = ref('');// 定义处理事件的函数
const handleMessage = (data) => {receivedMessage.value = data;console.log('收到数据:', data);
};// 组件挂载后订阅事件
onMounted(() => {emitter.on('messageEvent', handleMessage);
});// 组件卸载前取消订阅
onUnmounted(() => {emitter.off('messageEvent', handleMessage);
});
</script>

mitt 的其他常用 API:

  • emitter.all: 一个 Map,可以查看所有事件和处理函数。
  • emitter.off(eventType, handler): 移除特定事件的特定监听器。
  • emitter.emit(eventType): 触发事件,可不传数据。

方案二:使用 provide / inject 实现一个简单的事件总线

如果你不想引入第三方库,并且应用场景比较简单,可以利用 Vue 3 的 provideinject 特性,在根组件提供一个响应式对象作为事件总线。

1. 在根组件(如 App.vue)提供事件总线

<!-- App.vue -->
<template><PublisherComponent /><SubscriberComponent />
</template><script setup>
import { ref, provide } from 'vue';
import PublisherComponent from './components/PublisherComponent.vue';
import SubscriberComponent from './components/SubscriberComponent.vue';// 1. 创建一个响应式对象来存储事件和监听器(简化版)
const eventBus = ref({});// 2. 创建事件总线的方法
const eventBusMethods = {$on(event, callback) {if (!eventBus.value[event]) {eventBus.value[event] = [];}eventBus.value[event].push(callback);},$emit(event, ...args) {if (eventBus.value[event]) {eventBus.value[event].forEach(callback => callback(...args));}},// 可以自行实现 $off 等功能
};// 3. 将事件总线方法提供给所有子组件
provide('eventBus', eventBusMethods);
</script>

2. 在子组件中注入并使用

发布者组件:

<!-- PublisherComponent.vue -->
<template><button @click="$emitMessage">发送</button>
</template><script setup>
import { inject } from 'vue';// 注入事件总线
const eventBus = inject('eventBus');const $emitMessage = () => {eventBus.$emit('myEvent', '一些数据');
};
</script>

订阅者组件:

<!-- SubscriberComponent.vue -->
<template><div>消息: {{ message }}</div>
</template><script setup>
import { ref, inject, onMounted, onUnmounted } from 'vue';// 注入事件总线
const eventBus = inject('eventBus');
const message = ref('');const handleEvent = (data) => {message.value = data;
};onMounted(() => {eventBus.$on('myEvent', handleEvent);
});// 注意:这个简易实现需要更复杂的逻辑来实现 $off,这里省略了取消订阅
// onUnmounted(() => { ... });
</script>

三、Vue 3 事件总线 vs. 状态管理工具(如 Pinia)

特性事件总线(如 mitt)状态管理(如 Pinia)
目的组件间通信,传递事件消息全局状态管理,集中管理数据
数据流单向或双向,通常是“一发一收”单向数据流,状态可预测
数据持久性事件触发后即消失,不存储数据数据存储在 Store 中,是持久的
适用场景简单的、一次性的通知(如显示通知、表单提交完成)复杂的、需要共享和持久化的数据(如用户登录信息、购物车)
调试相对困难,事件是匿名的非常方便,有 DevTools 支持

总结与建议

  1. 对于 Vue 3,强烈推荐使用 mitt 来实现事件总线。它轻量、简单且完美契合 Vue 3 的理念。
  2. 将事件总线的创建逻辑放在一个独立的模块中(如 event-bus.js),便于管理和维护。
  3. 务必记住在组件卸载时(onUnmounted)取消事件监听,这是避免内存泄漏的关键。
  4. 如果应用的数据流变得非常复杂,需要多个组件共享和修改同一份数据,请考虑使用 Pinia 这类专门的状态管理库,而不是滥用事件总线。事件总线更适合处理行为通知,而非管理状态
http://www.dtcms.com/a/406971.html

相关文章:

  • OCR 如何精准识别越南身份证?
  • FPGA自学笔记--VIVADO FIFO IP核控制和使用
  • 张家界官方网站查询网ip138子域名
  • 【通信】无线PA 释义
  • 襄阳做公司网站的软件公司建立个人网站能赚钱吗
  • 赛迪顾问《2025中国虚拟化市场研究报告》解读丨虚拟化市场迈向“多元算力架构”,国产化与AI驱动成关键变量
  • 汕头公众号建设网站北京模板开发建站
  • 【Linux】UDP 网络编程
  • Redis 键空间 五大类型
  • seata部署与集成
  • ORM框架Java持久化层使用手册(mybatis,mybatisplus,jpa等)
  • 大型企业网站建设方案seo排名优化软件有用
  • 数据驱动下的高维数据破局术:降维处理的技术实战、选型指南与方法论沉淀
  • Java按顺序提取Word内容(文本+数学公式)
  • Python快速入门专业版(四十五):Python类的属性:实例属性、类属性与属性访问控制(封装特性)
  • 软考~系统规划与管理师考试——论文—— IT 服务监督管理专题 —— 范文
  • 深度解析社区运营中的技术实践:从数据驱动到智能优化的全面探索
  • 虚拟主机WordPress建站苏州网站建设如何选择
  • hello算法笔记 03
  • 沂水网站开发付钱做编程题目的网站
  • C++笔记(基础)string基础
  • 雨晨Win11PE_25H2_26200.6588紧急维护系统
  • 【鸿蒙心迹】摸蓝图,打地基
  • 小型教育网站的开发建设开题报告建设网咨询
  • 二级网站建设情况说明汕尾网站网站建设
  • 从零起步学习Redis || 第二章:Redis中数据类型的深层剖析讲解(下)
  • C++设计模式_创建型模式_原型模式Prototype
  • 简单直播TV1.4.3 | 一个软件观看四大平台,免去多应用切换烦恼
  • 设计模式-3D引擎中的设计模式
  • Linux安装配置Redis 7.2.3教程