vue3中事件总线

server/2025/3/14 15:22:46/

在 Vue 3 中,eventBus 的概念已经被弱,不推荐使用全局事件总线

你需要一个轻量级的事件总线,可以自己封装一个 EventBus 类,也有一些替代方案

1、使用第三方库(如 mitt 或 tiny-emitter)

mitt 是一个轻量级的事件发射器,适合在 Vue 3 中替代事件总线。它不依赖 Vue 实例,体积小且易于使用。

javascript">npm install mitt
javascript">// src/utils/eventBus.js
import mitt from 'mitt';export const emitter = mitt();
javascript">import { emitter } from './utils/eventBus';
// 触发事件
emitter.emit('event-name', data);
// 取消监听
emitter.off('event-name', handler);

2、依赖注入

provide 和 inject 是 Vue 3 推荐的父子组件通信方式,适合在组件树中传递数据。

javascript">// 父组件
import { provide } from 'vue';
export default {setup() {provide('message', 'Hello from Parent');}
};
javascript">// 子组件
import { inject } from 'vue';
export default {setup() {const message = inject('message');console.log(message);}
};

3、使用vuex或者pina

对于复杂的状态管理,推荐使用 Vuex 或 Pinia。它们提供了更强大的状态管理能力,适合大型项目。

javascript">// store.js
import { createStore } from 'vuex';
export default createStore({state: {message: 'Hello from Vuex'},mutations: {updateMessage(state, payload) {state.message = payload;}}
});
javascript">import { useStore } from 'vuex';
export default {setup() {const store = useStore();store.commit('updateMessage', 'New Message');console.log(store.state.message);}
};

4、使用props和emits

对于父子组件通信,props 和 emits 是最直接的方式。

javascript"><template><ChildComponent :message="message" @update="handleUpdate" />
</template><script>
import ChildComponent from './ChildComponent.vue';export default {components: {ChildComponent},data() {return {message: 'Hello from Parent'};},methods: {handleUpdate(newMessage) {this.message = newMessage;}}
};
</script>
javascript"><template><button @click="updateMessage">Update Message</button>
</template><script>
export default {props: ['message'],emits: ['update'],methods: {updateMessage() {this.$emit('update', 'New Message');}}
};
</script>

5、自己封装

在 Vue 3 中,你可以通过创建一个 Vue 实例作为事件总线来实现类似的功能。

javascript">// src/eventBus.js
import { createApp } from 'vue';const eventBus = createApp({});// 添加自定义事件方法
eventBus.config.globalProperties.$emit = function (event, ...args) {this._eventBus.emit(event, ...args);
};eventBus.config.globalProperties.$on = function (event, callback) {this._eventBus.on(event, callback);
};eventBus.config.globalProperties.$off = function (event, callback) {this._eventBus.off(event, callback);
};// 创建一个内部的事件总线
eventBus._eventBus = {events: {},on(event, callback) {if (!this.events[event]) {this.events[event] = [];}this.events[event].push(callback);},emit(event, ...args) {if (this.events[event]) {this.events[event].forEach(callback => {callback(...args);});}},off(event, callback) {if (this.events[event]) {this.events[event] = this.events[event].filter(cb => cb !== callback);}}
};export default eventBus;

子组件

javascript">// src/eventBus.js
import { createApp } from 'vue';const eventBus = createApp({});// 添加自定义事件方法
eventBus.config.globalProperties.$emit = function (event, ...args) {this._eventBus.emit(event, ...args);
};eventBus.config.globalProperties.$on = function (event, callback) {this._eventBus.on(event, callback);
};eventBus.config.globalProperties.$off = function (event, callback) {this._eventBus.off(event, callback);
};// 创建一个内部的事件总线
eventBus._eventBus = {events: {},on(event, callback) {if (!this.events[event]) {this.events[event] = [];}this.events[event].push(callback);},emit(event, ...args) {if (this.events[event]) {this.events[event].forEach(callback => {callback(...args);});}},off(event, callback) {if (this.events[event]) {this.events[event] = this.events[event].filter(cb => cb !== callback);}}
};export default eventBus;

父组件:

javascript"><template><ChildComponent />
</template><script>
import ChildComponent from './ChildComponent.vue';
import eventBus from '../eventBus';export default {components: {ChildComponent},created() {// 监听事件eventBus.$on('custom-event', this.handleCustomEvent);},beforeUnmount() {// 组件销毁时移除事件监听eventBus.$off('custom-event', this.handleCustomEvent);},methods: {handleCustomEvent(message) {console.log('Event received:', message);// 在这里处理逻辑}}
}
</script>

使用类方法封装一个事件总线

javascript">// src/utils/EventBus.jsclass EventBus {constructor() {this.events = {};}/*** 监听事件* @param {string} event - 事件名称* @param {Function} callback - 回调函数*/$on(event, callback) {if (!this.events[event]) {this.events[event] = [];}this.events[event].push(callback);}/*** 触发事件* @param {string} event - 事件名称* @param {...any} args - 传递给回调函数的参数*/$emit(event, ...args) {if (this.events[event]) {this.events[event].forEach(callback => {callback(...args);});}}/*** 移除事件监听* @param {string} event - 事件名称* @param {Function} callback - 回调函数*/$off(event, callback) {if (this.events[event]) {this.events[event] = this.events[event].filter(cb => cb !== callback);}}/*** 一次性监听事件* @param {string} event - 事件名称* @param {Function} callback - 回调函数*/$once(event, callback) {const onceCallback = (...args) => {callback(...args);this.$off(event, onceCallback);};this.$on(event, onceCallback);}
}// 创建一个 EventBus 实例
const eventBus = new EventBus();export default eventBus;

子组件

javascript"><template><button @click="handleClick">点击我</button>
</template><script>
import eventBus from '../utils/EventBus';export default {methods: {handleClick() {// 触发事件eventBus.$emit('custom-event', 'Hello from Child');}}
}
</script>

父组件

javascript"><template><ChildComponent />
</template><script>
import ChildComponent from './ChildComponent.vue';
import eventBus from '../utils/EventBus';export default {components: {ChildComponent},created() {// 监听事件eventBus.$on('custom-event', this.handleCustomEvent);},beforeUnmount() {// 组件销毁时移除事件监听eventBus.$off('custom-event', this.handleCustomEvent);},methods: {handleCustomEvent(message) {console.log('Event received:', message);// 在这里处理逻辑}}
}
</script>

http://www.ppmy.cn/server/174625.html

相关文章

基于django+vue的购物商城系统

开发语言&#xff1a;Python框架&#xff1a;djangoPython版本&#xff1a;python3.8数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat11开发软件&#xff1a;PyCharm 系统展示 系统首页 热卖商品 优惠资讯 个人中心 后台登录 管理员功能界面 用户管理 商品分类管理…

用nodejs加electron加roboticjs判断鼠标点击时是否在浏览器内部

要实现这个功能&#xff0c;你需要使用 Electron 来创建一个桌面应用&#xff0c;然后使用 RobotJS 监听鼠标点击事件&#xff0c;最后判断鼠标点击的位置是否在浏览器内部。以下是一个简单的示例&#xff1a; 首先&#xff0c;确保你已经安装了 Node.js 和 npm。然后&#xff…

MyBatis SqlSession 的作用,以及如何使用 SqlSession 执行 SQL 语句

SqlSession 是 MyBatis 中非常重要的一个接口&#xff0c;它代表了与数据库的一次会话&#xff08;session&#xff09;。 可以将 SqlSession 理解为 JDBC 中的 Connection 对象加上一系列操作数据库的方法。 它负责&#xff1a; SqlSession 的作用&#xff1a; 执行 SQL 语句…

一文说清docker及docker compose的应用和部署

前言 本文视频版教程&#xff1a;一个视频说清docker及docker compose的应用和部署&#xff08;https://cloud.tencent.com/developer/video/82177&#xff09; 本期教程将介绍Docker和Docker compose的基础应用&#xff0c;通过实际应用来讲解具体使用方法和两者的区别。 假…

1.2 CogPMAlignTool(模板匹配工具), CogFixtureTool(坐标系转换工具)

‌ CogPMAlignTool‌是高精度模板匹配工具&#xff0c;主要用于图像的特征定位和匹配。 ‌ CogFixtureTool是主要用于图像坐标系转换和对齐&#xff0c;就可以把当前拍照的图片固定到之前模板的那张图片。 相当于使用工具CogPMAlignTool‌来测量出当前图片与注册…

使用 OptiSLang 和 MotorCAD 构建一个强大的电机优化元模型

介绍 在本文中&#xff0c;我们将检查这些敏感性分析的结果&#xff0c;并构建一个健壮的元模型&#xff0c;作为优化过程的基础。 本文涵盖&#xff1a; 解释敏感性分析结果了解元模型及其在优化中的重要性构建和完善最佳预后模型 &#xff08;MOP&#xff09;使用预后系数…

蛋白质功能预测论文阅读记录2025(DPFunc、ProtCLIP)

前言 最近研究到瓶颈了&#xff0c;怎么优化都提升不了&#xff0c;遂开始看点最新的论文。 DPFunc 2025.1.2 Nature Communication 中南大学 论文地址&#xff1a;DPFunc: accurately predicting protein function via deep learning with domain-guided structure inform…

AtCoder ABC E - Min of Restricted Sum 题解

根据输入考虑建图&#xff0c;x、y两个下标的边权为z,建无向图 这样我们可以得到一些连通块。根据异或和的性质&#xff0c;对于每一个连通块&#xff0c;我们只要知道其中一个点的点权就能推出所有的点权。 最小值考虑贪心&#xff0c;针对当前连通图所有点权二进制数的每一…