组件卸载时未注销事件总线会导致内存泄漏,因监听器闭包持续引用组件实例;Vue 不管理自定义 eventBus 生命周期,必须手动 $off;推荐用 mitt 的 on() 返回的 off() 函数在 onUnmounted 中精准解绑,或改用 provide/inject、Pinia 订阅。
组件卸载时未注销事件总线,是内存泄漏的典型源头——它会让整个组件实例被监听器闭包持续引用,无法被垃圾回收。
Vue 本身不管理自定义事件总线(如 mitt、tiny-emitter 或手写的 Vue.prototype.$bus)的生命周期。一旦用 $on 绑定监听器,回调函数就形成闭包,隐式持有组件上下文(比如 this、ref、setup 中的变量)。只要没调用 $off,这个引用链就一直存在。
即使组件从 DOM 移除、响应式依赖被清理,eventBus 里仍存着指向已销毁组件的函数,导致内存无法释放。
mitt 等轻量库的 on() 方法会返回一个 off() 函数,这是唯一安全、精准的解绑方式:
不要用 emitter.off('user:update', handler) —— 这要求传入完全相同的函数引用,而箭头函数或每次渲染新建的函数会导致匹配失败,解绑失效。
事件总线本质是全局强引用,容易失控。更健壮的通信方式包括:
即使成功 $off,若监听器内部还启动了定时器、发起请求或创建 watch,这些新副作用仍需单独清理: