vue 事件總線EventBus的概念、使用以及注意點(diǎn)

vue組件中的數(shù)據(jù)傳遞最最常見的就是父子組件之間的傳遞。父傳子通過props向下傳遞數(shù)據(jù)給子組件;子傳父通過$emit發(fā)送事件,并攜帶數(shù)據(jù)給父組件。而有時(shí)兩個(gè)組件之間毫無關(guān)系,或者他們之間的結(jié)構(gòu)復(fù)雜,如何傳遞數(shù)據(jù)呢?這時(shí)就要用到 vue 中的事件總線 EventBus的概念

EventBus的簡介

EventBus又稱事件總線,相當(dāng)于一個(gè)全局的倉庫,任何組件都可以去這個(gè)倉庫里獲取事件

EventBus的使用

廢話不多說,直接開始使用EventBus

一、初始化

要用EventBus,首先要初始化一個(gè)EventBus,這里稱它為全局事件總線。

-第一種初始化方法

import Vue from 'vue'
//因?yàn)槭侨值囊粋€(gè)'倉庫',所以初始化要在全局初始化
const EventBus = new Vue()  

-第二種初始化方法(本文選用這種初始化方法)

//在已經(jīng)創(chuàng)建好的Vue實(shí)例原型中創(chuàng)建一個(gè)EventBus
Vue.prototype.$EventBus = new Vue()   

二、向EventBus發(fā)送事件

發(fā)送事件的語法:this.$EventBus.$emit(發(fā)送的事件名,傳遞的參數(shù))

已經(jīng)創(chuàng)建好EventBus后我們就需要向它發(fā)送需要傳遞的事件,以便其他組件可以向EventBus獲取

例子:有兩個(gè)組件A和B需要通信,他們不是父子組件關(guān)系,B事件需要獲得A事件里的一組數(shù)據(jù)data

<!-- A.vue 這里是以模塊化的方式講解的,即A組件和B組件分別各自
一個(gè).vue文件,所以代碼中會(huì)有導(dǎo)入的語法-->

<template>
    <button @click="sendMsg">發(fā)送MsgA</button>
</template>

<script> 
export default {
  data(){
    return{
        MsgA: 'A組件中的Msg'
    }
  },
  methods: {
    sendMsg() {
      /*調(diào)用全局Vue實(shí)例中的$EventBus事件總線中的$emit屬性,發(fā)送事
      件"aMsg",并攜帶A組件中的Msg*/
      this.$EventBus.$emit("aMsg", this.MsgA);
    }
  }
}; 
</script>

三、接收事件

接收事件的語法:this.$EventBus.$on(監(jiān)聽的事件名, 回調(diào)函數(shù))
A組件已經(jīng)向全局事件總線EventBus發(fā)送了一個(gè)aMsg事件,這時(shí)B組件就可以去aMsg監(jiān)聽這個(gè)事件,并可以獲得一些數(shù)據(jù)。

<!-- B.vue -->

<template>

  <!-- 展示msgB -->
  <p>{{msgB}}</p>
  
</template>

<script> 
export default {
  data(){
    return {
      //初始化一個(gè)msgB
      msgB: ''
    }
  },
  mounted() {
    /*調(diào)用全局Vue實(shí)例中的$EventBus事件總線中的$on屬性,監(jiān)聽A組件發(fā)送
    到事件總線中的aMsg事件*/
    this.$EventBus.$on("aMsg", (data) => {
      //將A組件傳遞過來的參數(shù)data賦值給msgB
      this.msgB = data;
    });
  }
};
</script>

B組件展示結(jié)果:

A組件中的Msg
這樣,B組件就輕松接收到了A組件傳遞過來的參數(shù),并成功展示了該參數(shù),這樣是不是就很簡單的解決了各組件之間的通訊呢?雖然EventBus是一個(gè)很輕便的方法,任何數(shù)據(jù)都可以往里傳,然后被別的組件獲取,但是如果用不好,容易出現(xiàn)很嚴(yán)重的BUG,所以接下來我們就來講解一下移除監(jiān)聽事件。

四、移除監(jiān)聽事件

在上一個(gè)例子中,我們A組件向事件總線發(fā)送了一個(gè)事件aMsg并傳遞了參數(shù)MsgA,然后B組件對該事件進(jìn)行了監(jiān)聽,并獲取了傳遞過來的參數(shù)。但是,這時(shí)如果我們離開B組件,然后再次進(jìn)入B組件時(shí),又會(huì)觸發(fā)一次對事件aMsg的監(jiān)聽,這時(shí)時(shí)間總線里就有兩個(gè)監(jiān)聽了,如果反復(fù)進(jìn)入B組件多次,那么就會(huì)對aMsg進(jìn)行多次的監(jiān)聽。

總而言之,A組件只向EventBus發(fā)送了一次事件,但B組件卻進(jìn)行了多次監(jiān)聽,EventBus容器中有很多個(gè)一模一樣的事件監(jiān)聽器這時(shí)就會(huì)出現(xiàn),事件只觸發(fā)一次,但監(jiān)聽事件中的回調(diào)函數(shù)執(zhí)行了很多次

1.解決辦法:在組件離開,也就是被銷毀前,將該監(jiān)聽事件給移除,以免下次再重復(fù)創(chuàng)建監(jiān)聽
2.語法:this.$EventBus.$off(要移除監(jiān)聽的事件名)

<!-- B.vue -->

<template>

  <!-- 展示msgB -->
  <p>{{msgB}}</p>
  
</template>

<script> 
export default {
  data(){
    return {
      //初始化一個(gè)msgB
      msgB: ''
    }
  },
  mounted() {
    /*調(diào)用全局Vue實(shí)例中的$EventBus事件總線中的$on屬性,監(jiān)聽A組件發(fā)送
    到事件總線中的aMsg事件*/
    this.$EventBus.$on("aMsg", (data) => {
      //將A組件傳遞過來的參數(shù)data賦值給msgB
      this.msgB = data;
    });
  },
  beforeDestroy(){
    //移除監(jiān)聽事件"aMsg"
    this.$EventBus.$off("aMsg")
  }
};
</script>

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容