Vue-eventBus

Vue-eventBus

父子组件通信与兄弟组件通信

vue组件非常常见的有父子组件通信,兄弟组件通信。

父子组件通信:方法有很多,比如:父组件通过 props 向下传数据给子组件,子组件通过 $emit 告诉父组件。
兄弟组件通信:如果两个页面没有任何引入和被引入关系,需要额外的组件来通信,如:事件总线、Vuex。

一、事件总线是什么

EventBus 又称为事件总线。在Vue中可以使用 EventBus 来作为沟通桥梁的概念,就像是所有组件共用相同的事件中心,可以向该中心注册发送事件或接收事件,所以组件都可以上下平行地通知其他组件。

EventBus若使用不慎,就会造成难以维护的“灾难”,因此才需要更完善的Vuex作为状态管理中心,将通知的概念上升到共享状态层次。 

优点

解决了多层组件之间繁琐的事件传播。
使用原理十分简单,代码量少

缺点

大家都知道vue是单页应用,如果你在某一个页面刷新了之后,与之相关的EventBus会被移除,这样就导致业务走不下去。
如果业务有反复操作的页面,EventBus在监听的时候就会触发很多次,也是一个非常大的隐患。这时候我们就需要好好处理EventBus在项目中的关系。通常在vue页面销毁时,同时移除EventBus事件监听。

由于是都使用一个Vue实例,所以容易出现重复触发的情景:两个页面都定义了同一个事件名,并且没有用$off销毁(常出现在路由切换时)。

二、使用

1.创建事件

首先需要创建事件总线并将其导出,以便其它模块可以使用或者监听它。

方法1、非全局事件组件

新建EventBus.js

import Vue from 'vue'
export const EventBus = new Vue()

法2、全局事件组件

在项目中的 main.js 初始化 EventBus。在main.js添加如下一行:

Vue.prototype.$EventBus = new Vue()

示例:

import Vue from 'vue'
import App from './App'
import router from './router'

Vue.config.productionTip = false

Vue.prototype.$EventBus = new Vue();

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
})

组件发送事件:this.$EventBus.$emit(…)

组件接收事件:this.$EventBus.$on(…)

移除事件

一般在销毁组件(也就是离开组件)时移除事件。

beforeDestroy(){
  EventBus.$off("eventName")
}

EventBus.$off() //移除EventBus所有事件监听器

EventBus.$off(‘eventName’) //移除’eventName’事件所有监听器

EventBus.$off(‘eventName’, callback) //只移除这个回调的监听器。

2.事件运用

本文父组件:CompA.vue,子组件1:ChildOne.vue,子组件2:ChildTwo.vue。子组件1发送事件给父组件和子组件2。

router/index.js

import Vue from 'vue'
import Router from 'vue-router'
import CompA from "@/components/CompA";

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/compA',
      name: 'compA',
      component: CompA,
    }
  ],
})

1.创建EventBus

新建EventBus.js

import Vue from 'vue'
export const EventBus = new Vue()

2.发送事件

components/ChildOne.vue

<template>
  <div class="childOne">
    <h1>childOne</h1>
    <button @click="sendEvent2CompA">发送事件给父组件(CompA)</button>
    <button @click="sendEvent2ChildTwo">发送事件给兄弟组件(ChildTwo)</button>
  </div>
</template>

<script>
import {EventBus} from "./EventBus"

export default {
  data() {
    return {
      count1: 0,
      count2: 0,
    }
  },
  methods:{
    sendEvent2CompA() {
      this.count1++;
      EventBus.$emit("compA", "compA事件触发次数:" + this.count1)
    },
    sendEvent2ChildTwo() {
      this.count2++;
      EventBus.$emit("childTwo", "childTwo事件触发次数:" + this.count2)
    }
  }
}
</script>

<style scoped>
</style>

3.接收事件

父组件:components/CompA.vue

<template>
  <div class="compA">
    <h1>compA</h1>
    compA收到的事件内容:{{msg}}<hr>
    <child-one></child-one><hr>
    <child-two></child-two>

  </div>
</template>

<script>
import {EventBus} from "./EventBus"
import ChildOne from "@/components/ChildOne";
import ChildTwo from "@/components/ChildTwo";

export default {
  components: {ChildOne, ChildTwo},
  data() {
    return {
      msg: "",
    }
  },
  mounted() {
    EventBus.$on("compA", (payload1)=> {
      this.msg = payload1;
    })
  }
}
</script>

<style scoped>

</style>

子组件2:components/ChildTwo.vue

<template>
  <div class="childTwo">
    <h1>childTwo</h1>
    childTwo收到的事件内容:{{msg}}
  </div>
</template>

<script>
import {EventBus} from "./EventBus"

export default {
  data() {
    return {
      msg: "",
    }
  },
  mounted() {
    EventBus.$on("childTwo", (payload1)=> {
      this.msg = payload1;
    })
  }
}
</script>

<style scoped>

</style>

事物都有两面性,没有好坏之分,且全在于使用者,好钢用在刀刃上,不滥用即可。有其他更好的方式则优先使用。

Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2022-2023 alan_mf
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信