Vue3中事件總線的具體使用
導讀
在Vue2中,我們遇到復雜的組件通信時,經常采用事件總線的方式來通信。其具體的思路就是實例化一個空白的Vue,並通過其提供的$on
、$once
、$emit
方法來進行通信。而在Vue3中,上述三個API已經被移除瞭,那麼我們又如何使用事件總線呢?
事件總線的本質
Vue2中的$on
、$once
、$emit
本質上就是其內部實現瞭一個EventEmitter
(事件派發器),每一個事件都和若幹回調相對應,隻要事件被觸發,那麼就將執行此事件所有對應的回調。同時,在JavaScript中,該思想被廣泛地使用,尤其在Node.js的事件機制中,就是創建瞭一個EventEmitter
實例,具體請自行查閱相關資料。因此,我們隻需要實現一個簡單的EventEmitter
,並全局傳遞到每一個組件中,就可以實現一個事件總線瞭。而全局傳遞,我們可以使用config.globalProperties
綁定到每一個組件,也可以在根組件(main)中,通過provide
提供總線,需要使用的組件使用inject
註入。下面就讓我們來實現一下吧。
構建一個EventEmitter
由於我們可能會有多條總線,我們還是把EventEmitter
寫成類的方式,每一條總線都將是一個EventEmitter
實例。以下是EventEmitter
的簡單實現,其隻實現瞭on
、once
、emit
三個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); } }
具體的代碼基本上還是很好理解的,就不在本文解釋瞭,具體請自行查閱相關的資料。
將EventEmitter實例化並全局引入
上文已經說瞭有兩種引入EventEmitter
的方法,這裡簡單地給個參考實例吧。
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>
但這種方法不太優雅,不方便定義多條總線,建議使用下述的方法。
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
更優雅一些,且不使用就不必使用inject註入。
結束語
到此這篇關於Vue3中事件總線的具體使用的文章就介紹到這瞭,更多相關Vue3 事件總線內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Vue3 全局實例上掛載屬性方法案例講解
- Vue3使用mitt進行組件通信的步驟
- 關於vue3 解決getCurrentInstance 打包後線上環境報錯問題
- vue3中實現使用element-plus調用message
- vue3組件通信的方式總結及實例用法