作为一名运用Vue的前端开发者,有时候会听到事情总线(EventBus)这个名词。但可能是我入行比较晚,我在Vue网站中并没有看到过事情总线的介绍,在项目中也没有运用过。那终究什么是事情总线?事情总线能够处理什么问题?

事情总线简介

事情总线是一种组件通讯办法,用于在工程的中的恣意组件中进行事情触发和数据传递。

经过在大局创建一个事情总线,一切组件(无论他们的联系是父子仍是兄弟仍是不相关)都能够运用同一个总线发送事情和监听事情,传输数据。这样通讯就能够不受组件间联系约束,完成灵敏的通讯能力。

Vue2完成事情总线

创建总线

首要创建一个Vue2项目,能够运用Vue CLI。然后在src/main.js中创建一个事情总线。创建的办法有两种:

  1. 新创建一个Vue实例
import Vue from 'vue'
import App from './App.vue'
Vue.prototype.$EventBus = new Vue()
new Vue({ render: h => h(App), }).$mount('#app')
  1. 运用已有的Vue实例
import Vue from 'vue'
import App from './App.vue'
new Vue({
  render: h => h(App),
  beforeCreate() { Vue.prototype.$EventBus = this; }
}).$mount('#app')

触发/接纳事情

咱们假设有两个组件A和B,A触发事情,B接纳事情。

  • 组件A
<template>
  <div> <p @click="add"> 点击增加 </p> </div>
</template>
<script>
export default {
  name: 'Add',
  data() { return { sum: 1, addNum: 1 } },
  methods: {
    add() {
      this.sum += this.addNum;
      this.addNum++;
      this.$EventBus.$emit('add', this.sum);
    }
  }
}
</script>
  • 组件B
<template>
  <div> <h1>收到数据: {{ sum }}</h1> </div>
</template>
<script>
export default {
  name: 'HelloWorld',
  data() { 
    return {
      sum: 1,
      listenFun: (sum) => { this.sum = sum; }
    }
  },
  mounted() {
    this.$EventBus.$on('add', this.listenFun)
  },
  beforeDestroy() {
    this.$EventBus.$off('add', this.listenFun)
  },
}
</script>

能够看到事情总线的完成办法实际上十分简略,就是把一个Vue实例挂载为一个大局属性,在这个实例上触发事情,监听事情即可。如果不需要监听时,要记得毁掉监听事情。

其它组件通讯办法

Vue2有许多组件间的通讯办法,这里总结一下:

  1. 组件Props 父组件向子组件传递数据
  2. 组件事情Emit 子组件触发事情;父组件监听事情,接纳数据
  3. 组件v-model 经过props和事情完成父子组件数据的双向绑定
  4. 依靠注入 父组件向子孙组件传递数据
  5. Attributes 没有被组件声明为props或emits的属性;父组件向子组件传递数据
  6. 状况办理 大局同享的数据办理,一般运用Pinia或许Vuex等东西
  7. 事情总线 大局组件同享的事情办理
  8. 模板引证ref 父组件主动调用子组件办法,可传递数据
  9. 其它办法 能够存放数据的公共位置,比如Storage, Window等。

事情总线的优缺陷

经过事情总线的完成,咱们能够了解到事情总线能够十分简略的完成大局组件同享的事情办理,传递数据等。既然如此简略,那Vue为什么没有引荐作为官方的组件通讯办法?为什么即使Vue官方并无引荐,但却有许多开发者运用事情总线。咱们结合上面的其它组件通讯办法,来评论下事情总线的优缺陷。

优点

  1. 完成大局恣意组件同享的数据传输
    检查上面的通讯办法,咱们能够看到Vue提供的大部分办法都有组件联系的约束,大部分是父组件向子组件向子孙组件之间传递。而事情总线却没有任何约束。
  2. 完成十分简略
    运用状况办理东西也能够完成数据传递,可是这些东西都要引入依靠库,有自己的运用办法。虽然并不麻烦,可是都没有事情总线运用这么简略。
  3. 大局的事情办理器
    组件通讯除了传递数据,另一个效果是实时触发事情,针对事情进行操作。检查上面的组件通讯办法,咱们发现除事情总线外,大局的通讯只是数据的传递,没有事情的触发。经过监听状况办理和Storage数据等,能够变相完成事情的办理,可是并没有事情总线清晰和直接。

缺陷

  • 事情监听只能被动接纳数据,不能随时获取状况
    如果需要随时获取状况,显然仍是状况办理东西更适合。
  • vue3不提供事情总线能力
    在vue3中$on $off等实例办法已被移除,组件实例不再完成事情触发接口。官方引荐运用 mitt 等外部东西。

还有运用不小心带来的许多问题。例如:

  • 事情名同享同一个命名空间
  • 不毁掉事情监听器
    如果在不运用后忘记毁掉事情监听器,会造成难以排查的Bug或许引发功能问题。
  • 误毁掉同名事情其它监听器
    比如多个组件都监听了同一事情’add’。其间某个组件毁掉了’add’事情下的一切监听器this.$EventBus.$off('add'),就会影响其他的组件。
  • 其它问题 例如调试困难,耦合性高等等。

总结

事情总线作为一种大局的组件通讯办法,符合订阅发布模式,因为其简略有用的运用办法,受到部分开发者的欢迎。可是因为各种运用不小心和维护带来的问题,官方和许多开发者也不引荐运用:

在绝大多数情况下,不鼓舞运用大局的事情总线在组件之间进行通讯。虽然在短期内往往是最简略的处理方案,但从长时间来看,它维护起来总是令人头疼。根据具体情况来看,有多种事情总线的替代方案. —— Vue3迁移攻略

可是事情总线就完全不能运用么?也并不是。首要上面说的各种运用问题,能够经过预先拟定开发标准+严厉代码审核处理。其次,检查上面的通讯办法,其实Vue并没有直接的大局事情通知办法,作为一种大局事情通知东西,仍是有它共同的效果的。是否能够运用,仍是要具体问题具体分析。

参考