[Vue] 跟著 Vue 闖蕩前端世界 - 07 組件溝通 event bus

我們都知道 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 使用上很方便,但由於維護及偵錯性不高,因此在使用時請把握以下幾個原則:

  1. 避免濫用,只限於多階層或同層組件溝通使用,若單層父子溝通不應透過 event bus 進行,需使用 props / v-on 進行溝通。
  2. 事件名稱一定要有統一的命名規範,避免衝突產生。
  3. 記得有監聽的地方,就要有相對位置去清除。
  4. 如果專案規模大,最好就直接使用 vuex 來妥善管理共同狀態。

 

參考資訊


Use a Global Event Bus

 

測試代碼已上傳 GitHub 中,有需要的朋友可以參考一下。
若有更好的建議或做法再請不吝指導一下囉! 感謝!

 


希望此篇文章可以幫助到需要的人

若內容有誤或有其他建議請不吝留言給筆者喔 !