There are times when building a Vue application that you realize that the standard parent-child model of intra-component communication just isn’t cutting it anymore. Everything gets too ridged and it gets harder and harder to add more layers to the application. Parent-child just doesn’t scale once you’re really working with a real-world project. Who is in control of the data when the components are nested five layers deep?

One way to handle this—coming along with its own pros and cons—is using an Event Bus.

An Event Bus is a PubSub object that allows the components to communicate via broadcast messages.

In other words, an Event Bus is like a Twitter stream where anyone can post messages and anyone can read those messages. More importantly, components only need to read the messages they really care about and can post messages without knowing who might want them. It allows your components to be decoupled from each other since they don’t talk directly to other components but instead communicate through well-documented (please make them well-documented) messages in the application.

The best way to create an Event Bus for your Vue application is to use the mitt pubsub library.

Why use mitt when I see everywhere people saying to use new Vue()?

Good question. The main reason why is that the methods needed for an event bus—on() and off()—are no longer supported in Vue 3. Also, using an empty Vue instance was always kind of a hack anyway. So we’re going to use a library that is custom built for just this purpose.

Adding an Event Bus to a Vue application

First, you’ll want to install mitt via npm:

npm install --save mitt

Then, create a service that creates an event bus for your components to use:

import mitt from 'mitt';

const EventBus = mitt();

export default EventBus;

And that’s it! When your component wants to communicate outside of itself, it just emits an event:

import EventBus from '../services/EventBus.js';

...

EventBus.emit('book.added', book);

And other components can listen for new events on the same bus. This is usually done in the component’s mounted() method:

import EventBus from '../services/EventBus.js';

...

mounted() {
    EventBus.on('book.added', this.addBook);
},
methods: {
    addBook(book) {
        this.book = book;
    }
},

...

If your component is unloaded, you’ll have to manually unload the listeners too, or the event handlers will still be called. Like most things in programming, and in life, if you turn it on, you should turn it off.

In Vue 2, this will happen in the beforeDestroy lifecycle hook:

beforeDestroy() {
    EventBus.off('book.added', this.addBook);
}

And in Vue 3, it will happen in the beforeUnmount lifecycle hook:

beforeUnmount() {
    EventBus.off('book.added', this.addBook);
}

If you know you need an Event Bus, this is an easy way in Vue 2 and Vue 3 to set one up.