08.Vue事件总线(EventBus)

vue组件非常常见的有父子组件通信,兄弟组件通信。而父子组件通信就很简单,**父组件会通过 props 向下传数据给子组件,当子组件有事情要告诉父组件时会通过 $emit 事件告诉父组件。**今天就来说说如果两个页面没有任何引入和被引入关系,该如何通信了?

如果咱们的应用程序不需要类似Vuex这样的库来处理组件之间的数据通信,就可以考虑Vue中的 事件总线 ,即 **EventBus**来通信。

一.EventBus事件总线简介

EventBus又称事件总线,相当于一个全局的仓库,任何组件都可以去这个仓库里获取事件

img

二.事件总线(EventBus)的使用

2.1 事件总线的初始化

img

要用EventBus,首先要初始化一个EventBus,这里称它为全局事件总线。

2.1.1 第一种初始化方法

import Vue from 'vue'
//因为是全局的一个'仓库',所以初始化要在全局初始化
const EventBus = new Vue()     
复制代码

2.1.2 第二种初始化方法(本文选用这种初始化方法)

//在已经创建好的Vue实例原型中创建一个EventBus
Vue.prototype.$EventBus = new Vue()   
复制代码
import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

//给Vue绑定属性
Vue.prototype.xyz=100;
// Vue.prototype.$EventBus=vm

new Vue({
  beforeCreate(){
  //安装事件总线
  Vue.prototype.abc=900;
  Vue.prototype.$EventBus=this
 },
  render: h => h(App),
}).$mount('#app')
复制代码

2.2 向EventBus发送事件

img

发送事件的语法:this.$EventBus.$emit(发送的事件名,传递的参数)

已经创建好EventBus后我们就需要向它发送需要传递的事件,以便其他组件可以向EventBus获取。

例子:有两个组件A和B需要通信,他们不是父子组件关系,B事件需要获得A事件里的一组数据data

<!--  -->
<template>
  <div id="demo01">
    <h1>Demo01组件</h1>
    <h2>从Demo02接受的收据:{{msg}}</h2>
    <button @click="fasong">发送数据给Demo02</button>
  </div>
</template>

<script>
export default {
  name: "Demo01",
  data () {
    return {
      msg: ''
    }
  },
  methods: {
    test01 (data) {
      console.log(data);
      this.msg = data
    },
    fasong () {
      this.$EventBus.$emit("send", "我是Demo01页面");
    }
  },
  mounted () {
    // console.log(this);
    // 2.接受全局的haha事件
    this.$EventBus.$on('haha', this.test01)
  }
}
</script>
<style scoped>
#demo01 {
  background-color: red;
  padding: 20px;
  margin-bottom: 20px;
}
</style>
复制代码

2.3 接受EventBus事件

img

接收事件的语法:this.$EventBus.$on(监听的事件名, 回调函数)

A组件已经向全局事件总线EventBus发送了一个aMsg事件,这时B组件就可以去aMsg监听这个事件,并可以获得一些数据。

<!--  -->
<template>
  <div id="demo02">
    <h1>Demo02组件</h1>
    <button @click="sendData">发送事件给Demo01</button>
    <h2>从Demo01接受的收据:{{msg}}</h2>
  </div>
</template>

<script>
export default {
  name: "Demo02",
  data () {
    return {
      msg: ''
    }
  },
  methods: {
    sendData () {
      // 触发全局的haha事件
      this.$EventBus.$emit("haha", '老王')
    },
    display (data) {
      console.log(data);
      this.msg = data
    }
  },
  mounted () {
    // console.log(this.abc);
    console.log(this.$EventBus);
    this.$EventBus.$on("send", this.display)
  }
}
</script>
<style scoped>
#demo02 {
  background-color: blue;
  padding: 20px;
}
</style>
复制代码

GIF 2021-7-11 21-04-42.gif

2.4 移除监听事件

img

虽然EventBus是一个很轻便的方法,任何数据都可以往里传,然后被别的组件获取,但是如果用不好,容易出现很严重的BUG,所以接下来我们就来讲解一下移除监听事件。

在上一个例子中,我们Demo02组件向事件总线发送了一个事件sendData并传递了参数**’老王’**,然后Demo01组件对该事件进行了监听,并获取了传递过来的参数。但是,这时如果我们离开Demo01组件,然后再次进入Demo01组件时,又会触发一次对事件sendData的监听,这时时间总线里就有两个监听了,如果反复进入sendData组件多次,那么就会对sendData进行多次的监听。

总而言之,A组件只向EventBus发送了一次事件,但B组件却进行了多次监听,EventBus容器中有很多个一模一样的事件监听器这时就会出现,事件只触发一次,但监听事件中的回调函数执行了很多次

  • ==解决办法:在组件离开,也就是被销毁前,将该监听事件给移除,以免下次再重复创建监听==
  • 语法:this.$EventBus.$off(要移除监听的事件名)
<!--  -->
<template>
  <div id="demo02">
    <h1>Demo02组件</h1>
    <button @click="sendData">发送事件给Demo01</button>
    <h2>从Demo01接受的收据:{{msg}}</h2>
  </div>
</template>

<script>
export default {
  name: "Demo02",
  data () {
    return {
      msg: ''
    }
  },
  methods: {
    sendData () {
      // 触发全局的haha事件
      this.$EventBus.$emit("haha", '老王')
    },
    display (data) {
      console.log(data);
      this.msg = data
    }
  },
  mounted () {
    // console.log(this.abc);
    console.log(this.$EventBus);
    this.$EventBus.$on("send", this.display)
  },
  beforeDestory () {
    //移除事件监听send
    this.$EventBus.off("send")
  }
}
</script>
<style scoped>
#demo02 {
  background-color: blue;
  padding: 20px;
}
</style>
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享