组件通信BUS模式及原理

简介: vue组件通信方式是个老生常谈的话题了,最全面的莫过于 vuex,最简单的就是父子组件 props 传值,今天我们重点来说说经常提到的 bus 模式。

vue组件通信方式是个老生常谈的话题了,最全面的莫过于 vuex,最简单的就是父子组件 props 传值,今天我们重点来说说经常提到的 bus 模式。


bus使用


  1. 使用Vue创建新实例
Vue.prototype.$bus = new Vue();
复制代码

$bus 实际就是个 Vue 实例对象



  1. 定义事件监听函数
// A.vue
created() {
  this.$bus.$on('setName', (name) => {
    console.log('receive:' + name)
  })
}
复制代码

  1. 触发事件
// B.vue
mounted() {
  this.$bus.$emit('setName', 'Job')
}
复制代码

  1. 移除事件
// A.vue
destroyed() {
  this.$bus.$ff('setName')
}
复制代码


我们在这边只传递了一个事件名参数 setName,这时会移除所有的 setName 监听函数,在实际使用的时候,我们一般会添加第二个参数来指定移除的监听函数


this.$bus.$ff('setName', fn); // fn的指针地址需要和创建($on)添加的函数相同,这点和removeEventListener是一致的
复制代码


bus使用注意事项


bus模式实际是非常简单的,简单加上日常并不一定需要去使用,以至于我们经常忘记如何使用它。使用的时候有几个需要注意的点


  1. 在组件中使用 this.$bus 之前要先往原型上注册该实例 Vue.prototype.$bus = new Vue()

  2. 在触发事件 this.$bus.$emit(xxx) 之前应该先定义监听函数 this.$bus.$on(xxx, fn)

  3. 在组件销毁的时候,如有必要是需要移除事件的 this.$bus.$off(xxx, fn),不然会多次重复监听

bus模式的原理


知道 订阅发布模式 的一眼就能看出 bus 其实就是一个 订阅发布 的实现。通过 $on 添加订阅,通过 $emit 触发通知广播。关于订阅发布模式可以看看浅谈订阅发布实现vue


所以说,我们的 bus 模式实际是利用了 vue 中的一个 订阅发布 实现,我们通过实例方法 $on$emit$off 来触发 vue 是事件订阅中心。


我们接着来看看其源码部分


  1. $on


Vue.prototype.$on = function (event: string | Array<string>, fn: Function): Component {
  const vm: Component = this
  // 可以使用数组同时添加多个订阅
  if (Array.isArray(event)) {
    for (let i = 0, l = event.length; i < l; i++) {
      vm.$on(event[i], fn)
    }
  } else {
    // 订阅:往事件中心vm._events添加事件回调函数fn
    (vm._events[event] || (vm._events[event] = [])).push(fn)
    // ...
  }
  return vm
}
复制代码

  1. $emit
Vue.prototype.$emit = function (event: string): Component {
  const vm: Component = this
  // 先取事件中心的event类型回调函数
  let cbs = vm._events[event]
  if (cbs) {
    cbs = cbs.length > 1 ? toArray(cbs) : cbs
    const args = toArray(arguments, 1)
    const info = `event handler for "${event}"`
    // 依次触发事件回调函数fn
    for (let i = 0, l = cbs.length; i < l; i++) {
      invokeWithErrorHandling(cbs[i], vm, args, vm, info)
    }
  }
  return vm
}
复制代码



  1. $off
Vue.prototype.$off = function (event?: string | Array<string>, fn?: Function): Component {
  const vm: Component = this
  // 没有event参数将移除全部
  if (!arguments.length) {
    vm._events = Object.create(null)
    return vm
  }
  // 可移除事件数组
  if (Array.isArray(event)) {
    for (let i = 0, l = event.length; i < l; i++) {
      vm.$off(event[i], fn)
    }
    return vm
  }
  // 没有回调函数则直接退出
  const cbs = vm._events[event]
  if (!cbs) {
    return vm
  }
  // 没有fn参数将移除所有event类型回调
  if (!fn) {
    vm._events[event] = null
    return vm
  }
  // 移除特定事件
  // 可以发现只会移除第一个符合条件的函数
  let cb
  let i = cbs.length
  while (i--) {
    cb = cbs[i]
    if (cb === fn || cb.fn === fn) {
      cbs.splice(i, 1)
      break
    }
  }
  return vm
}
复制代码


总结


我们今天分析了bus模式的组件通信方式及其实现原理,整体比较简单 good good staduy day day up


相关文章
|
28天前
qiankun框架中基于actions机制实现主应用与子应用间的双向通信
qiankun框架中基于actions机制实现主应用与子应用间的双向通信
105 0
|
6月前
|
JavaScript 前端开发 API
【前端--Vue】组件之间的多种通信方式,一文彻底搞懂组件通信!
【前端--Vue】组件之间的多种通信方式,一文彻底搞懂组件通信!
【前端--Vue】组件之间的多种通信方式,一文彻底搞懂组件通信!
|
6月前
|
安全 搜索推荐 Linux
D-Bus深度解析:系统总线与会话总线的区别与应用
D-Bus深度解析:系统总线与会话总线的区别与应用
195 2
|
物联网 API
0x01 . BlueNRG-1 BLE同时作为主、从设备的场景是如何实现的?
0x01 . BlueNRG-1 BLE同时作为主、从设备的场景是如何实现的?
|
6月前
组件间的通信
组件间的通信
|
6月前
|
消息中间件 存储 缓存
概述Linux进程间通信模式
【2月更文挑战第14天】
CTK框架 - 通信 - 事件通信和信号槽通信
CTK框架中的事件监听,即观察者模式流程上是这样:接收者注册监听事件->发送者发送事件->接收者接收到事件并响应;相比调用插件接口,监听事件插件间依赖关系更弱,不用指定事件的接收方和发送方是谁。比如我们需要弹出一个界面,可以使用事件来弹出。
254 0
|
Android开发
浅谈组件之间的通信—EventBus
EventBus是一款针对Andoid优化的发布/订阅事件总线,主要功能是替Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息,优点是开销小,代码更优雅,以及将发送者和接收者进行解耦
139 0
|
开发者
驱动开发:基于事件同步的反向通信
在之前的文章中`LyShark`一直都在教大家如何让驱动程序与应用层进行`正向通信`,而在某些时候我们不仅仅只需要正向通信,也需要反向通信,例如杀毒软件如果驱动程序拦截到恶意操作则必须将这个请求动态的转发到应用层以此来通知用户,而这种通信方式的实现有多种,通常可以使用创建Socket套接字的方式实现,亦或者使用本章所介绍的通过`事件同步`的方法实现反向通信。
202 0
|
JSON JavaScript 小程序
【小程序】组件通信
【小程序】组件通信
209 0
【小程序】组件通信