2026/4/18 17:58:32
网站建设
项目流程
长春做网站推荐选吉网传媒好,各大门户网站,产品质量推广营销语,店标设计logo设计Vue3中使用Mitt事件总线实现组件通信。Mitt是一个轻量级的事件库#xff0c;可作为全局事件总线替代方案。文章介绍了基本使用方法#xff1a;创建事件总线实例、定义事件类型、在组件中发射和监听事件#xff0c;并强调组件卸载时需取消监听以避免内存泄漏。还展示了高级用…Vue3中使用Mitt事件总线实现组件通信。Mitt是一个轻量级的事件库可作为全局事件总线替代方案。文章介绍了基本使用方法创建事件总线实例、定义事件类型、在组件中发射和监听事件并强调组件卸载时需取消监听以避免内存泄漏。还展示了高级用法工厂模式创建多总线、封装Vue插件、CompositionAPI封装Hook。最后对比了Mitt与Vue原生通信方式的差异建议谨慎使用事件总线优先考虑props/emit或provide/inject等更明确的通信方式。Vue 3 中使用 Mitt 事件总线Mitt 是一个轻量级的事件发射/监听库在 Vue 3 中可以作为全局事件总线的替代方案。安装npm install mitt # 或 yarn add mitt # 或 pnpm add mitt基本使用1.创建事件总线实例方式一创建全局事件总线// src/utils/eventBus.ts import mitt from mitt type Events { // 定义事件类型 user-login: { userId: string; username: string } user-logout: void notification: string update-count: number // 使用通配符监听所有事件 *: { type: string; payload?: any } } const eventBus mittEvents() export default eventBus方式二在 Composition API 中使用vue!-- ComponentA.vue -- script setup langts import { onUnmounted } from vue import eventBus from /utils/eventBus // 发射事件 const emitLogin () { eventBus.emit(user-login, { userId: 123, username: 张三 }) } // 监听事件 eventBus.on(notification, (message) { console.log(收到通知:, message) }) // 监听所有事件 eventBus.on(*, (type, payload) { console.log(事件类型: ${type}, payload) }) // 组件卸载时取消监听 onUnmounted(() { eventBus.off(notification) // 或者取消所有监听 // eventBus.all.clear() }) /script2.在多个组件中使用vue!-- Header.vue -- script setup langts import eventBus from /utils/eventBus const logout () { eventBus.emit(user-logout) } const sendNotification () { eventBus.emit(notification, 新消息) } /scriptvue!-- Sidebar.vue -- script setup langts import { ref, onMounted, onUnmounted } from vue import eventBus from /utils/eventBus const notification ref() const handleNotification (message: string) { notification.value message setTimeout(() notification.value , 3000) } onMounted(() { eventBus.on(notification, handleNotification) }) onUnmounted(() { eventBus.off(notification, handleNotification) }) /script高级用法1.使用工厂模式创建多个事件总线// src/utils/eventBusFactory.ts import mitt from mitt export function createEventBusT() { return mittT() } // 创建不同的事件总线 export const uiEventBus createEventBus{ modal-open: { id: string } modal-close: string }() export const dataEventBus createEventBus{ data-loaded: any[] data-error: Error }()2.封装为 Vue 插件// src/plugins/eventBus.ts import { type App } from vue import mitt, { type Emitter } from mitt // 事件类型定义 type Events { [key: string]: any } // 创建全局事件总线 const eventBus: EmitterEvents mittEvents() export const EventBusPlugin { install(app: App) { // 全局属性 app.config.globalProperties.$eventBus eventBus // 提供/注入 app.provide(eventBus, eventBus) } } // 在 Composition API 中使用的 Hook export function useEventBus() { const eventBus injectEmitterEvents(eventBus) if (!eventBus) { throw new Error(Event bus not provided) } return eventBus } export default eventBusmain.ts// main.ts import { createApp } from vue import { EventBusPlugin } from /plugins/eventBus import App from ./App.vue const app createApp(App) app.use(EventBusPlugin) app.mount(#app)3.在 Composition API 中封装 Hooktypescript// src/composables/useEventBus.ts import { onUnmounted } from vue import eventBus, { type Handler } from /utils/eventBus export function useEventBus() { const listeners: Array[string, Handler] [] const emit T any(event: string, payload?: T) { eventBus.emit(event, payload) } const on T any(event: string, handler: (payload: T) void) { eventBus.on(event, handler as Handler) listeners.push([event, handler as Handler]) } const off T any(event: string, handler: (payload: T) void) { eventBus.off(event, handler as Handler) const index listeners.findIndex( ([e, h]) e event h handler ) if (index -1) { listeners.splice(index, 1) } } const once T any(event: string, handler: (payload: T) void) { const onceHandler (payload: T) { handler(payload) off(event, onceHandler) } on(event, onceHandler) } // 自动清理监听器 onUnmounted(() { listeners.forEach(([event, handler]) { eventBus.off(event, handler) }) listeners.length 0 }) return { emit, on, off, once } }vue!-- 使用封装的 Hook -- script setup langts import { useEventBus } from /composables/useEventBus const { emit, on, once } useEventBus() // 发送事件 const sendEvent () { emit(custom-event, { data: test }) } // 监听事件 on(custom-event, (payload) { console.log(收到事件:, payload) }) // 只监听一次 once(one-time-event, (payload) { console.log(只会触发一次:, payload) }) /script与 Vue 原生方法的比较特性MittVue 3 的emit/propsProvide/Inject通信范围任意组件间父子组件间祖先-后代组件间类型支持TypeScript 友好TypeScript 友好TypeScript 友好耦合度低高中适用场景全局事件、兄弟组件父子组件层级深的组件最佳实践类型安全// 正确定义事件类型 type Events { user-updated: User cart-changed: CartItem[] }及时清理// 组件卸载时取消监听 onUnmounted(() { eventBus.off(event-name, handler) })避免过度使用优先使用 props/emit 进行父子组件通信优先使用 provide/inject 进行层级通信只在需要跨多级/兄弟组件通信时使用事件总线错误处理const { emit, on } useEventBus() on(error-event, (error) { // 统一错误处理 console.error(事件错误:, error) })注意事项内存泄漏务必在组件卸载时取消事件监听调试困难事件总线可能导致数据流不清晰替代方案对于复杂应用考虑使用 Pinia 进行状态管理Mitt 在 Vue 3 中是一个简单有效的跨组件通信方案但应谨慎使用避免滥用导致代码难以维护。