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
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)
}
}
})
Links
- Original post by Arvid Kahl
- Vue.js docs about “Non Parent-Child Communication”