Vue3中事件總線的具體使用
導(dǎo)讀
在Vue2中,我們遇到復(fù)雜的組件通信時(shí),經(jīng)常采用事件總線的方式來通信。其具體的思路就是實(shí)例化一個(gè)空白的Vue,并通過其提供的$on、$once、$emit方法來進(jìn)行通信。而在Vue3中,上述三個(gè)API已經(jīng)被移除了,那么我們又如何使用事件總線呢?
事件總線的本質(zhì)
Vue2中的$on、$once、$emit本質(zhì)上就是其內(nèi)部實(shí)現(xiàn)了一個(gè)EventEmitter(事件派發(fā)器),每一個(gè)事件都和若干回調(diào)相對(duì)應(yīng),只要事件被觸發(fā),那么就將執(zhí)行此事件所有對(duì)應(yīng)的回調(diào)。同時(shí),在JavaScript中,該思想被廣泛地使用,尤其在Node.js的事件機(jī)制中,就是創(chuàng)建了一個(gè)EventEmitter實(shí)例,具體請(qǐng)自行查閱相關(guān)資料。因此,我們只需要實(shí)現(xiàn)一個(gè)簡(jiǎn)單的EventEmitter,并全局傳遞到每一個(gè)組件中,就可以實(shí)現(xiàn)一個(gè)事件總線了。而全局傳遞,我們可以使用config.globalProperties綁定到每一個(gè)組件,也可以在根組件(main)中,通過provide提供總線,需要使用的組件使用inject注入。下面就讓我們來實(shí)現(xiàn)一下吧。
構(gòu)建一個(gè)EventEmitter
由于我們可能會(huì)有多條總線,我們還是把EventEmitter寫成類的方式,每一條總線都將是一個(gè)EventEmitter實(shí)例。以下是EventEmitter的簡(jiǎn)單實(shí)現(xiàn),其只實(shí)現(xiàn)了on、once、emit三個(gè)API。
class EventEmitter{
constructor(){
this.callbacks={};
}
on(envetName,callback){
if(!Array.isArray(this.callbacks[envetName])){
this.callbacks[envetName]=[];
}
this.callbacks[envetName].push(callback);
}
emit(eventName,...args){
if(Array.isArray(this.callbacks[eventName])){
this.callbacks[eventName].forEach(callback=>callback(...args));
}
}
off(eventName,callback){
if(!Array.isArray(this.callbacks[eventName])){
return
}
if(callback){
this.callbacks[eventName].forEach(cb=>{
if(callback===cb){
this.callbacks[eventName].splice(this.callbacks[eventName].indexOf(callback),1);
}
});
} else{
this.callbacks[eventName]=[];
}
}
once(eventName,callback){
const that=this;
const fn=function(){
callback.apply(that,[...arguments]);
that.off(eventName,fn);
}
that.on(eventName,fn);
}
}
具體的代碼基本上還是很好理解的,就不在本文解釋了,具體請(qǐng)自行查閱相關(guān)的資料。
將EventEmitter實(shí)例化并全局引入
上文已經(jīng)說了有兩種引入EventEmitter的方法,這里簡(jiǎn)單地給個(gè)參考實(shí)例吧。
config.globalProperties方法
在main.js中
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
const app=createApp(App);
app.config.globalProperties.$event=new EventEmitter();
app.mount('#app')
在組件中:
//Comp1
<script setup>
import {getCurrentInstance} from "vue"
const vm=getCurrentInstance();
vm.proxy.$event.on('test',()=>{
console.log('test event emit!')
})
</script>
//Comp2
<script setup>
import {getCurrentInstance} from "vue"
const vm=getCurrentInstance();
vm.proxy.$event.emit('test',"a","b")
</script>
但這種方法不太優(yōu)雅,不方便定義多條總線,建議使用下述的方法。
provide/inject
在main.js中
provide("eventBus1",new EventEmitter());
provide("eventBus2",new EventEmitter());
在組件中
//Comp1
<script setup>
import {inject} from "vue";
const bus1=inject("eventBus1")
bus1.on("bus1-on-event",()=>{
console.log('eventBus1 on event emit!')
})
</script>
//Comp2
<script setup>
import {inject} from "vue";
const bus1=inject("eventBus1")
const bus2=inject("eventBus2")
bus2.on("bus2-on-event",()=>{
console.log('eventBus2 on event emit!')
})
bus1.emit("bus1-on-event")
</script>
//Comp3
<script setup>
import {inject} from "vue";
const bus2=inject("eventBus2")
bus2.emit("bus2-on-event")
</script>
此方法中,使用inject也比使用getCurrentInstance再.proxy更優(yōu)雅一些,且不使用就不必使用inject注入。
結(jié)束語
到此這篇關(guān)于Vue3中事件總線的具體使用的文章就介紹到這了,更多相關(guān)Vue3 事件總線內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用vue2.6實(shí)現(xiàn)抖音【時(shí)間輪盤】屏保效果附源碼
前段時(shí)間看抖音,有人用時(shí)間輪盤作為動(dòng)態(tài)的桌面壁紙,一時(shí)間成為全網(wǎng)最火的電腦屏保,后來小米等運(yùn)用市場(chǎng)也出現(xiàn)了【時(shí)間輪盤】,有點(diǎn)像五行八卦,感覺很好玩,于是突發(fā)奇想,自己寫一個(gè)網(wǎng)頁版小DEMO玩玩,需要的朋友可以參考下2019-04-04
vue圓環(huán)百分比進(jìn)度條組件功能的實(shí)現(xiàn)
在一些頁面設(shè)置進(jìn)度條效果給人一種很好的體驗(yàn)效果,今天小編教大家vue圓環(huán)百分比進(jìn)度條組件功能的實(shí)現(xiàn)代碼,代碼超級(jí)簡(jiǎn)單啊,感興趣的朋友快來看下吧2021-05-05
Vue?動(dòng)態(tài)路由的實(shí)現(xiàn)詳情
這篇文章主要介紹了Vue?動(dòng)態(tài)路由的實(shí)現(xiàn),動(dòng)態(tài)路由是一個(gè)常用的功能,根據(jù)后臺(tái)返回的路由json表,前端動(dòng)態(tài)顯示可跳轉(zhuǎn)的路由項(xiàng),本文主要實(shí)現(xiàn)的是后臺(tái)傳遞路由,前端拿到并生成側(cè)邊欄的一個(gè)形勢(shì),需要的朋友可以參考一下2022-06-06
Vue 解決在element中使用$notify在提示信息中換行問題
這篇文章主要介紹了Vue 解決在element中使用$notify在提示信息中換行問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-11-11

