vue中EventBus实现原理

488 阅读2分钟

vue中组件通信方式多种多样,eventBus可以帮助我们将两个兄弟组件关联起来,实现状态监听,数据流通,其类似发布订阅模式,在其一个组件中来监听事件,另一个组件中触发事件后这个组件监听到状态发生变化,就会调用相应的方法来处理数据

EventBus之事件总线

在Vue中可以使用 EventBus 来作为沟通桥梁的概念,定义一个事件处理中心,我们可以借助vue实例上的两个方法:$on$emit来向这个中心注册或是接收事件,所有组件都可以通过引入这个中心,通过自定的事件名与处理方法来完成数据交互

如何使用EventBus

一、初始化

在项目src路径下新建一个.js文件,引入vue并向外暴露出一个vue实例

import Vue from 'vue' export default new Vue()

二、在需要的组件中引入该js文件

demo1组件:触发事件

`
import Bus from '../utils/eventBus'
export default {
  methods: {
    change () {
      Bus.$emit('changeName', '李四')
    }
  }
}
`

demo2组件:监听事件

`
import Bus from '../utils/eventBus'
export default {
  data () {
    return {
      name: '张三'
    }
  },
  components: { AboutVue },
  mounted () {
    Bus.$on('changeName', (name) => {
      this.name = name
    })
  }
  }
`

当demo1组件中触发了change事件时,demo2中的name就会修改成demo1传过来的 '李四'

这是如何实现的呢? 我们可以思考一下

实现原理

  1. 需要传递被监听事件的方法$on
  2. 需要记录传递到事件总线的方法以及回调函数
  3. 需要触发事件的方法$emit
  4. 找到对应的事件名,触发对应的回调函数
  5. 记录事件与触发事件有对应关系(想到键值对)

开始实现

一、定义事件总线eventBus

`
class EvenetBus{
// listener 用来接收事件名,以及事件名对应的回调函数,这个回调函数可能有多个,所以应该对应一个数组
  constructor () {
    this.$listener = {}
  }
  // 监听事件
  $on(eventName,callback){}
  // 触发事件
  $emit(eventName,val){}
  }
  
  // 将事件中心暴露出去
  export dafault new EventBus()
`

完善事件逻辑

  1. $on中接收的事件,需要被$listener注册
  2. $emit触发的事件,需要被$listener触发
`
$on(eventName,callback){
    // 判断listener中是否已存在该事件,有则添加回调方法,无则注册事件
    if(this.listener[eventName]){
      this.listener[eventName].push(callback)
    }else{
    this.listener[eventName] = eventName
    }
}
// 触发事件后,调用事件处理逻辑即传过来的回调
$emit(eventName,val){
 // 找到$on中对应的事件名,调用执行其中存储的函数
this.listener[eventName].forEach(cb => cb(val))
}
`

验证逻辑可行性

点击按钮触发change事件:

image.png

发现name成功修改

image.png

逻辑验证成功,