我們都知道 vuex 可以幫助我們統一管理狀態,但是若情況沒有這麼複雜或專案規模不大的時候,是可以考慮使用 event bus 來作為組件溝通的橋樑。
前言
使用 event bus 來作為溝通橋樑的概念就像是所有組件共用相同的事件中心,可以向該中心註冊發送事件或接收事件,所有組件都可以上下平行地通知其他組件,但也就是太方便所以若不謹慎使用,會造成難以維護的災難產生,因此才需要更完善的 vuex 作為狀態管理中心,將通知的概念提升到共享狀態層次。說了這麼多,如果網站規模不大不複雜,共用狀態或多階組件互動其實並沒有這麼多的時候也可以先從 event bus 著手,因此本文就來學習一下怎麼實作 event bus 機制吧。
實作
建立 event bus 實體
建立 vue 實體作為事件中心,另外透過 defineProperty 定義 $bus 屬性來取得 root vue instance 中 bus 資料,方便各組件取用。
import Vue from 'vue'
// 使用一個空的 Vue 實例作為事件中心
var bus = new Vue();
// 定義 Vue prototype 的 $bus 屬性存取描述器(Accessor descriptor)
// 方便 event bus 被任何子元件使用
Object.defineProperty(Vue.prototype, '$bus', {
get() {
return this.$root.bus;
}
});
export default bus;
加入 root vue instance 資料
將 event bus 加入 root Vue instance 的 data 中,讓每個子組件都共享事件中樞
import Vue from 'vue'
import App from './App'
import router from './router'
import eventBus from './setup/eventBus'
new Vue({
el: '#app',
data() {
return {
// Bind our event bus to our $root Vue model
bus: eventBus
}
},
router,
template: '<App/>',
components: { App }
})
發送事件
可以在任意組件利用 $bus 取得事件中樞,再透過此 event bus 呼叫 emit 送出事件及傳遞的資料。
<script>
export default {
methods: {
doSomethingSpecial: function() {
// emit the event and pass with it an object of "event data".
this.$bus.$emit('specialEvent', {
msg: 'This message came from the specialEvent.',
title: 'Trigger by PropsTester'
});
}
},
}
</script>
接收事件
在任何一個存在的組件中設置以下監聽事件後,都可以接收到訊息。
切記要記得在組件銷毀前,清除所監聽的所有事件!
<script>
export default {
name: 'xxx',
created() {
// [註冊監聽事件]
this.$bus.$on('specialEvent', event => {
toastr.info(event.msg, event.title)
});
},
beforeDestroy: function() {
// [銷毀監聽事件]
// 最好在组件銷毀前,清除 specialEvent 所有監聽
// 如果要指定哪個監聽對應方法,就需要傳入第二個參數(對應$on設定的方法)
this.$bus.$off('specialEvent');
}
}
</script>
驗證通訊結果
點選後確實可以接收到事件,並正確顯示傳遞出的參數
結論
雖然 event bus 使用上很方便,但由於維護及偵錯性不高,因此在使用時請把握以下幾個原則:
- 避免濫用,只限於多階層或同層組件溝通使用,若單層父子溝通不應透過 event bus 進行,需使用 props / v-on 進行溝通。
- 事件名稱一定要有統一的命名規範,避免衝突產生。
- 記得有監聽的地方,就要有相對位置去清除。
- 如果專案規模大,最好就直接使用 vuex 來妥善管理共同狀態。
參考資訊
測試代碼已上傳 GitHub 中,有需要的朋友可以參考一下。
若有更好的建議或做法再請不吝指導一下囉! 感謝!
若有更好的建議或做法再請不吝指導一下囉! 感謝!
希望此篇文章可以幫助到需要的人
若內容有誤或有其他建議請不吝留言給筆者喔 !