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>