前言
Vue2 与 Vue3 事件总线区别
Vue2
使用$on
,$off
和$once
实例方法,创建一个事件总线,可在整个应用中做全局事件监听;Vue3
移除$on
,$off
和$once
实例方法 ,但提供了解决方案,使用库 mitt 或 tiny-emitter;- 且注意
Vue3
保留了实例方法 $emit,用于触发由父组件声明式添加的事件处理函数;
解决方案
定义
Vue2 实现
// 文件 bus.js
import Vue from 'vue'const bus = new Vue({});export default bus;
Vue3 实现
题外话, 库 tiny-emitter 最后一次更新是 5年前,库 mitt 更新是 2023.07.05
。所以这里选择 库 mitt。
先安装:
npm i mitt
再定义。注意代码 6-9 行
有转换,因为库 mitt
中的方法是不带前缀 $
,为了与 Vue
方法名兼容使用。
// 文件 bus.js
import mitt from 'mitt'const bus = mitt();// mitt 库中的方法是不带前缀$。为了与 Vue 方法名匹配。此处有转换。
bus.$on = bus.on;
bus.$off = bus.off;
bus.$emit = bus.emit;export default bus;
有个坑
Vue2/Vue3
可传多个额外参数;- 库
mit
t 只能传一个额外参数,建议是object
类型;
引入
Vue2
和 Vue3
引入方式一样。
import bus from './bus.js'
使用
Vue2
和 Vue3
使用方式也一样。但有上述提到的传递参数个数问题!
// 触发事件
bus.$emit('foo', 'test');// 监听事件
bus.$on('foo', foo);// 取消监听
bus.$off('foo', foo);// 测试方法
function foo(e) {console.log('foo', e);
}
延伸知识
vm. e m i t 与 b u s . emit 与 bus. emit与bus.emit 区别
vm.$emit
- 是
Vue
实例方法,且 Vue2 / Vue3 都有此方法; - 用于子组件向父组件传递消息,通过方法
$emit
触发父组件上的自定义事件,并传参数; - 可传递任意 多个额外参数;
// 子组件,触发事件
this.$emit('on-param-change', p1, p2);// 父组件,监听事件
<my-parents @on-param-change="onParamChange" />
onParamChange (p1, p2) {console.log(p1, p2);
}
bus.$emit
- 是上述
库 mitt
的方法,注意原生是emit
,不带$
; - 可创建一个事件总线,在整个应用中做全局事件监听;
- 只能传递 一个额外参数;
import bus from './bus.js'// 触发事件
bus.$emit('on-param-change', {p1, p2});// 监听事件
bus.$on('on-param-change', (obj) {console.log(obj.p1, obj.p2);
});
如果你没接触过GoGoCode,下小节可忽略
GoGoCode 中的 $emit 方法
GoGoCode
转换文件 /utils/gogocodeTransfer
封装了 $on, $once, $off, $emit
方法。
-
也是
Vue3
移除$on
,$off
和$once
实例方法 的解决方案之一; -
但在自动转换过程中,它把
vm.$emit
和bus.$emit
的方法都转了; -
所以出现了第三种方式;
GoGoCode 兼容 vm.$emit 方法
- GoGoCode 方式:第一个参数是
this
组件实例对象;
// 使用 gogocode 的写法
import { $on, $off, $emit } from './utils/gogocodeTransfer'$emit(this, 'tool-click', type, num);
- vm.$emit 方式:可传多个额外参数。如果是父子组件传递消息,推荐此原生方式;
// 使用 Vue 原生的写法
this.$emit('tool-click', type, num);
GoGoCode 兼容 bus.$emit 方法
- GoGoCode 方式:第一个参数是
bus
对象(mitt
)。它的有优点是可传递任意多个额外参数;
import { $on, $off, $emit } from './utils/gogocodeTransfer'// 触发事件,bus 是 mitt 对象
$emit(bus, 'on-param-change', p1, p2);// 监听事件,bus 是 mitt 对象
$on(bus, 'on-param-change', (p1, p2) {console.log(p1, p2);
});
- bus.$emit 方式:注意只能传一个额外参数。
import bus from './bus.js'// 触发事件
bus.$emit('on-param-change', {p1, p2});// 监听事件
bus.$on('on-param-change', (obj) {console.log(obj.p1, obj.p2);
});