$on/$off用于Vue 2中事件总线场景,如非父子组件通信、WebSocket消息通知、动态键盘监听等,需在mounted注册、beforeDestroy精准移除以避免内存泄漏。

在 Vue 2 的 Options API 中,$on 和 $off 是实例方法,用于手动注册和移除自定义事件监听器。它们不适用于父子组件通信(推荐用 props/$emit),而主要用于**同一组件内部或跨组件的事件总线(Event Bus)场景**,且必须注意监听器的生命周期管理,避免内存泄漏。
什么时候需要用 $on / $off?
典型场景是:使用一个空的 Vue 实例作为事件总线,在多个组件间传递消息(Vue 2 常见模式)。例如:
- 非父子关系的组件需要响应某个全局操作(如“用户登出”)
- 第三方库或定时任务触发后通知组件更新(如 WebSocket 收到消息)
- 需要在组件内动态开启/关闭某类回调(如键盘快捷键监听)
正确注册与清理监听器(关键!)
监听器必须在组件销毁前移除,否则会持续持有对组件实例的引用,导致无法被 GC,引发内存泄漏。推荐在 mounted 中 $on,在 beforeDestroy(Vue 2)中 $off:
export default {
mounted() {
// 注册监听器,保存引用以便后续移除
this.myHandler = (data) => {
console.log('收到事件:', data)
}
this.$bus.$on('user-logout', this.myHandler)
},
beforeDestroy() {
// 精准移除:传入同一函数引用
this.$bus.$off('user-logout', this.myHandler)
}
}
注意:不能写成 this.$bus.$on('user-logout', () => { ... }),因为箭头函数每次创建都是新引用,$off 无法匹配移除。
支持的 $off 用法(按推荐顺序)
-
移除指定事件 + 指定处理函数(最安全):
this.$bus.$off('event', handler) -
移除指定事件的所有监听器:
this.$bus.$off('event') -
移除所有事件的所有监听器(慎用,影响其他组件):
this.$bus.$off()
替代方案:优先考虑更现代的做法
如果只是父子通信,直接用 props 和 $emit,无需 $on/$off;如果项目已升级 Vue 3,应改用 mitt 或 tiny-emitter 等轻量事件库,并配合 onBeforeUnmount 清理;Vue 2 中也可封装一个 mixin 或组合式工具函数统一管理事件绑定/解绑。


















