一,前言
1.在vue
中,当组件之间层级不相近时,或者层级涉及的较多的时候,普通的组件数据传递方式就会显得比较无力,例如下面的A
组件要和B
组件通信
2.vue2
中提供了事件总线的方式,通过事件的发送和事件的监听可以做到上下平行数据传送
3.事件总线使用了发布订阅模式的软件设计模式。
二,事件总线使用
1.初始化一个事件总线(中介)
(1)我们可以新建一个js
文件导出Vue
实例,作为中介,不需要任何的配置项,在需要的地方,导入这个js
文件
export default const eventBus = new Vue()
(2)我们也可以在vue
入口文件注册一个全局事件总线:
Vue.prototype.$EventBus = new Vue()
2.消息发布
(1)当使用js
导出实例时,使用实例的$emit
发布消息,第一个参数是发布消息的key
,之后的参数是传递的数据
eventBus.$emit('eventName', 1,2,3)
(2)使用全局事件总线时在组件内部使用注册的$EventBus
来使用$emit
发布消息
this.$EventBus.$emit('eventName', 1,2,3)
3.订阅消息
(1)通过实例方法$on
监听一个事件,第一个参数是订阅的消息的,第二个参数是一个回调函数,函数参数是接受的数据,
eventBus.$on('eventName',(n1,n2,n3)=>{})
//or
this.$EventBus.$emit('eventName', 1,2,3)
(2)当有消息发布时,所有订阅此消息的地方都会触发回调函数
(3)注意在vue
中,当我们要在回调函数里使用到组件的this
时,要使用箭头函数,因为箭头函数的this
是在被定义时上下文的this
。
4.取消订阅
(1)使用$off
实例方法可以取消某个订阅。
//移除指定key的所有订阅
eventBus.$off('eventName')
//移除指定key的某一个订阅回调
eventBus.$off('eventName',callback)
//移除所有订阅
eventBus.$off()
(2)当不订阅时,要移除监听,否则订阅的事件会一直占着内存,导致内存泄露
三,vue3
中事件总线
1.在vue3
中,App
的创建方法改成了createApp()
,prototype
属性也被取消了,所以无法使用之前Vue.prototype.$bus = new Vue()
的方式使用事务总线。
2.更主要的原因是在vue3
中移除了组件实例的$on
,$off
方法。
3.vue3
已经不支持事件总线的方式,但是官方推荐:如果仍需要使用事件总线模式,可以使用外部的、实现了事件触发器接口的库,例如 mitt
或 tiny-emitter
。
4.这里简单记录一下mitt
的使用
(1)首先安装mitt
:npm install --save mitt
(2)在代码中使用:
import mitt from "mitt"
import {createApp} from "vue"
const app = createApp()
//挂载事务总线 globalProperties 替代了之前的prototype
app.config.globalProperties.$bus = new mitt()
//在组件A中使用事务总线触发某个动作
this.$bus.emit("EVENTTYPE");
//在组件B中监听动作的发生
this.$bus.on("EVENTTYPE",()=>{
console.log("EVENTTYPE发生了")})