[Frontend Note] Event Bus in Vue

A summary of how to use event bus in Vue2.x and Vue3

Posted by Jamie on Thursday, March 24, 2022

EventBus from Vue2.x to Vue3

Preface

In Vue2, when you want to do cross-component communication, besides Vuex, the event bus pattern is very common in smaller projects. But Vue3 removed $on, $off, $emit and similar APIs, so the event bus can no longer rely on those APIs to listen. However, in Vue3 you can use the third-party library mitt.

Event Bus in Vue2.x

Method 1: Add an event bus property in main.js

In main.js:

//Add a property on the Vue instance
Vue.prototype.$eventBus = new Vue();

In the component that listens for events:

this.$on("event name",(*args)=>{
	...
})

In the component that emits events:

this.$emit("event name",*args)

Method 2: Create a new Vue instance directly and use it as the EventBus

In eventBus.js:

import Vue from "vue";
export const EventBus = new Vue();

In the component that listens for events:

import { EventBus } from "@/eventBus";
EventBus.$on("event name",(...args)=>{
	...
})

In the component that emits events:

import { EventBus } from "@/eventBus";
EventBus.$emit("event name",...args)

Method 3: Refactor eventBus into a plugin

This is the approach used in a previous company project, because we needed to use the EventBus on both Vue and on window at the same time.

In EventBus.js:

import Vue from 'vue';

class EventBus {
    constructor() {
        this.bus = new Vue();
    }
    on(event, handler) {
        this.bus.$on(event, handler);
    }
    once(event, handler) {
        this.bus.$once(event, handler);
    }
    off(event, handler) {
        this.bus.$off(event, handler);
    }
    emit(event, ...args) {
        this.bus.$emit(event, ...args);
    }
}
export default {
    install(Vue) {
        const eventBus = new EventBus();
        Vue.prototype.$EventBus = eventBus;
        window.EventBus = eventBus;
    }
};

Then register it in main.js:

import Vue from 'vue';
import EventBus from '@/plugins/EventBus';

Vue.use(EventBus);

After that you can listen for and emit events the same way as above.

Event Bus in Vue3

Since Vue3 removed $on, $off, $emit, etc., we use the third-party library mitt instead.

Create an entry file for the eventBus (entry.ts):

import mitt, { Emitter } from 'mitt';
const EventBus: Emitter<any> = mitt();

export default EventBus;

In my current project I treat the event bus as a hook, so I write it like this:
(useDataHook.ts)

import EventBus from '@/hooks/eventBus/entry';
import { onMounted } from 'vue';
export default function () {
    onMounted(() => {
        EventBus.on("event name",(...args)=>{
			...
		})
    });
}

(DemoListener.vue)

import useDataHook from '@/hooks/eventBus/useDataHook';
setup(){
	useDataHook()
}

(DemoTrigger.vue)

import EventBus from '@/hooks/eventBus/entry';
setup(){
	function demoTrigger(){
		EventBus.emit("event name", ...args)
	}
	return {demoTrigger}
}

ChangeLog

  • 20260501–translate by claude code