vue3中事件总线

打印 上一主题 下一主题

主题 1038|帖子 1038|积分 3118

在 Vue 3 中,eventBus 的概念已经被弱,不保举使用全局事件总线,
你需要一个轻量级的事件总线,可以自己封装一个 EventBus 类,也有一些替换方案
1、使用第三方库(如 mitt 或 tiny-emitter)

mitt 是一个轻量级的事件发射器,适合在 Vue 3 中替换事件总线。它不依赖 Vue 实例,体积小且易于使用。
  1. npm install mitt
复制代码
  1. // src/utils/eventBus.js
  2. import mitt from 'mitt';
  3. export const emitter = mitt();
复制代码
  1. import { emitter } from './utils/eventBus';
  2. // 触发事件
  3. emitter.emit('event-name', data);
  4. // 取消监听
  5. emitter.off('event-name', handler);
复制代码
2、依赖注入

provide 和 inject 是 Vue 3 保举的父子组件通信方式,适合在组件树中传递数据。
  1. // 父组件
  2. import { provide } from 'vue';
  3. export default {
  4.   setup() {
  5.     provide('message', 'Hello from Parent');
  6.   }
  7. };
复制代码
  1. // 子组件
  2. import { inject } from 'vue';
  3. export default {
  4.   setup() {
  5.     const message = inject('message');
  6.     console.log(message);
  7.   }
  8. };
复制代码
3、使用vuex或者pina

对于复杂的状态管理,保举使用 Vuex 或 Pinia。它们提供了更强大的状态管理能力,适合大型项目。
  1. // store.js
  2. import { createStore } from 'vuex';
  3. export default createStore({
  4.   state: {
  5.     message: 'Hello from Vuex'
  6.   },
  7.   mutations: {
  8.     updateMessage(state, payload) {
  9.       state.message = payload;
  10.     }
  11.   }
  12. });
复制代码
  1. import { useStore } from 'vuex';
  2. export default {
  3.   setup() {
  4.     const store = useStore();
  5.     store.commit('updateMessage', 'New Message');
  6.     console.log(store.state.message);
  7.   }
  8. };
复制代码
4、使用props和emits

对于父子组件通信,props 和 emits 是最直接的方式。
  1. <template>
  2.   <ChildComponent :message="message" @update="handleUpdate" />
  3. </template>
  4. <script>
  5. import ChildComponent from './ChildComponent.vue';
  6. export default {
  7.   components: {
  8.     ChildComponent
  9.   },
  10.   data() {
  11.     return {
  12.       message: 'Hello from Parent'
  13.     };
  14.   },
  15.   methods: {
  16.     handleUpdate(newMessage) {
  17.       this.message = newMessage;
  18.     }
  19.   }
  20. };
  21. </script>
复制代码
  1. <template>
  2.   <button @click="updateMessage">Update Message</button>
  3. </template>
  4. <script>
  5. export default {
  6.   props: ['message'],
  7.   emits: ['update'],
  8.   methods: {
  9.     updateMessage() {
  10.       this.$emit('update', 'New Message');
  11.     }
  12.   }
  13. };
  14. </script>
复制代码
5、自己封装

在 Vue 3 中,你可以通过创建一个 Vue 实例作为事件总线来实现类似的功能。
  1. // src/eventBus.js
  2. import { createApp } from 'vue';
  3. const eventBus = createApp({});
  4. // 添加自定义事件方法
  5. eventBus.config.globalProperties.$emit = function (event, ...args) {
  6.   this._eventBus.emit(event, ...args);
  7. };
  8. eventBus.config.globalProperties.$on = function (event, callback) {
  9.   this._eventBus.on(event, callback);
  10. };
  11. eventBus.config.globalProperties.$off = function (event, callback) {
  12.   this._eventBus.off(event, callback);
  13. };
  14. // 创建一个内部的事件总线
  15. eventBus._eventBus = {
  16.   events: {},
  17.   
  18.   on(event, callback) {
  19.     if (!this.events[event]) {
  20.       this.events[event] = [];
  21.     }
  22.     this.events[event].push(callback);
  23.   },
  24.   
  25.   emit(event, ...args) {
  26.     if (this.events[event]) {
  27.       this.events[event].forEach(callback => {
  28.         callback(...args);
  29.       });
  30.     }
  31.   },
  32.   
  33.   off(event, callback) {
  34.     if (this.events[event]) {
  35.       this.events[event] = this.events[event].filter(cb => cb !== callback);
  36.     }
  37.   }
  38. };
  39. export default eventBus;
复制代码
子组件
  1. // src/eventBus.js
  2. import { createApp } from 'vue';
  3. const eventBus = createApp({});
  4. // 添加自定义事件方法
  5. eventBus.config.globalProperties.$emit = function (event, ...args) {
  6.   this._eventBus.emit(event, ...args);
  7. };
  8. eventBus.config.globalProperties.$on = function (event, callback) {
  9.   this._eventBus.on(event, callback);
  10. };
  11. eventBus.config.globalProperties.$off = function (event, callback) {
  12.   this._eventBus.off(event, callback);
  13. };
  14. // 创建一个内部的事件总线
  15. eventBus._eventBus = {
  16.   events: {},
  17.   
  18.   on(event, callback) {
  19.     if (!this.events[event]) {
  20.       this.events[event] = [];
  21.     }
  22.     this.events[event].push(callback);
  23.   },
  24.   
  25.   emit(event, ...args) {
  26.     if (this.events[event]) {
  27.       this.events[event].forEach(callback => {
  28.         callback(...args);
  29.       });
  30.     }
  31.   },
  32.   
  33.   off(event, callback) {
  34.     if (this.events[event]) {
  35.       this.events[event] = this.events[event].filter(cb => cb !== callback);
  36.     }
  37.   }
  38. };
  39. export default eventBus;
复制代码
父组件:
  1. <template>
  2.   <ChildComponent />
  3. </template>
  4. <script>
  5. import ChildComponent from './ChildComponent.vue';
  6. import eventBus from '../eventBus';
  7. export default {
  8.   components: {
  9.     ChildComponent
  10.   },
  11.   created() {
  12.     // 监听事件
  13.     eventBus.$on('custom-event', this.handleCustomEvent);
  14.   },
  15.   beforeUnmount() {
  16.     // 组件销毁时移除事件监听
  17.     eventBus.$off('custom-event', this.handleCustomEvent);
  18.   },
  19.   methods: {
  20.     handleCustomEvent(message) {
  21.       console.log('Event received:', message);
  22.       // 在这里处理逻辑
  23.     }
  24.   }
  25. }
  26. </script>
复制代码
使用类方法封装一个事件总线
  1. // src/utils/EventBus.js
  2. class EventBus {
  3.   constructor() {
  4.     this.events = {};
  5.   }
  6.   /**
  7.    * 监听事件
  8.    * @param {string} event - 事件名称
  9.    * @param {Function} callback - 回调函数
  10.    */
  11.   $on(event, callback) {
  12.     if (!this.events[event]) {
  13.       this.events[event] = [];
  14.     }
  15.     this.events[event].push(callback);
  16.   }
  17.   /**
  18.    * 触发事件
  19.    * @param {string} event - 事件名称
  20.    * @param {...any} args - 传递给回调函数的参数
  21.    */
  22.   $emit(event, ...args) {
  23.     if (this.events[event]) {
  24.       this.events[event].forEach(callback => {
  25.         callback(...args);
  26.       });
  27.     }
  28.   }
  29.   /**
  30.    * 移除事件监听
  31.    * @param {string} event - 事件名称
  32.    * @param {Function} callback - 回调函数
  33.    */
  34.   $off(event, callback) {
  35.     if (this.events[event]) {
  36.       this.events[event] = this.events[event].filter(cb => cb !== callback);
  37.     }
  38.   }
  39.   /**
  40.    * 一次性监听事件
  41.    * @param {string} event - 事件名称
  42.    * @param {Function} callback - 回调函数
  43.    */
  44.   $once(event, callback) {
  45.     const onceCallback = (...args) => {
  46.       callback(...args);
  47.       this.$off(event, onceCallback);
  48.     };
  49.     this.$on(event, onceCallback);
  50.   }
  51. }
  52. // 创建一个 EventBus 实例
  53. const eventBus = new EventBus();
  54. export default eventBus;
复制代码
子组件
  1. <template>
  2.   <button @click="handleClick">点击我</button>
  3. </template>
  4. <script>
  5. import eventBus from '../utils/EventBus';
  6. export default {
  7.   methods: {
  8.     handleClick() {
  9.       // 触发事件
  10.       eventBus.$emit('custom-event', 'Hello from Child');
  11.     }
  12.   }
  13. }
  14. </script>
复制代码
父组件
  1. <template>
  2.   <ChildComponent />
  3. </template>
  4. <script>
  5. import ChildComponent from './ChildComponent.vue';
  6. import eventBus from '../utils/EventBus';
  7. export default {
  8.   components: {
  9.     ChildComponent
  10.   },
  11.   created() {
  12.     // 监听事件
  13.     eventBus.$on('custom-event', this.handleCustomEvent);
  14.   },
  15.   beforeUnmount() {
  16.     // 组件销毁时移除事件监听
  17.     eventBus.$off('custom-event', this.handleCustomEvent);
  18.   },
  19.   methods: {
  20.     handleCustomEvent(message) {
  21.       console.log('Event received:', message);
  22.       // 在这里处理逻辑
  23.     }
  24.   }
  25. }
  26. </script>
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

东湖之滨

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表