Use a global event bus instead of a state manager


Disclaimer : This tip is (largely) inspired by this post by Arvid Kahl

What is a global event bus ?

In Vue.js, components are supposed to interact through Parent-Child Communication. It should go props down, events up (down being parent to child).

Most applications require components to communicate with other components than their parent or children. The recommended way to do so is to implement a state management solution such as Vuex (an official, supported Flux-like implementation) or even VueStash.

However this may come with a bit of overhead for relatively simple apps, where you have only a few cases of cross-components communication. This is where you could use a global event bus.

Global because it is available everywhere in your app.

Event because it is an event-based system, similar to Javascript’s event implementation (similar, but different).

Bus is the term used in computing for data transfer between components (for instance between your graphics card and the mother board, you use a PCI bus).

Again, this is not the recommended way to do things in most applications. It is mentioned in the official docs though, but keep in mind that if you use it in a complex application, you’ll most likely end up with a big event mess.

Event bus instantiation

The event bus is just a Vue component. It should be a dedicated component, even if any component could be used (your root component for instance).

const EventBus = new Vue()

To make it available everywhere in your app, you may attach it to the Vue global object.

const EventBus = new Vue()

Object.defineProperties(Vue.prototype, {
  $bus: {
    get: function () {
      return EventBus
    }
  }
})

Trigger global events

You can now trigger events in your components :

export default {
  name: 'my-component',
  methods: {
    triggerMyEvent () {
      this.$bus.$emit('my-event', { ... pass some event data ... })
    }
  }
}

Or directly in your HTML template

<div>
  <button @click="$bus.$emit('my-event')">Click to trigger event</button>
</div>

Listen to events

Events can be listened to in any component.

export default {
  name: 'my-component',
  created () {
    this.$bus.$on('my-event', ($event) => {
      console.log('My event has been triggered', $event)
    })
  }
}

Including the event bus component itself

const EventBus = new Vue({
  created () {
    this.$on('my-event', this.handleMyEvent)
  },
  methods: {
    handleMyEvent ($event) {
      console.log('My event caught in global event bus', $event)
    }
  }
})

Latest posts

Use Vue.js to create custom web components

Include Vue.js components in any HTML/JS application

Vue.js Component Style Guide

General purpose recommandations for writing Vue.js components code

How to use Docker containers for Vue.js applications

Get started with Docker and Vue.js

Hide elements during loading using "v-cloak"

You probably need this directive and didn't know it

Using Bootstrap with Vue.js

Question is : do you really need Boostrap ?

Build, test and deploy your Vue.js app easily with Gitlab

Introduction to Continuous Integration using free Gitlab tools

Another way to declare Vuex modules

`vuex-module` provides a syntax to write your store modules' state, actions, getters, etc. You may want to use it.

Simple state management, simpler than Vuex

Vue Stash makes it easy to share reactive data between components. An alternative to Vuex.

Hybrid Vue.js app in Cordova : desktop or mobile ?

A simple hack to know if the code is executed in a website or in the Cordova version of your app

Does Vue.js require jQuery ?

No it doesn't. But you might find it useful, here's why.