Create a global event bus in Vue.js

Global Event Bus in Vue.js

Let’s imagine you are creating a relatively big application using vue. This means, you’ll have a large collection of components in different levels. Now, you need a proper mechanism for communicating between the components.

You can pass data through the “props” to the child components. That’s fine. But what if you need to communicate with some other component which is not a child component? Things are getting complicated there. But not anymore. Let’s take advantage of the event mechanism in vue.

There are many ways to solve this problem. I’ll show you a simple and effective mechanism that I used in a recent project. We’ll be communicating with the components through a global event bus. Now what’s an event bus? Yeah that’s right. Just like the name indicates, it transport data between components and provide a means for communication between any components. Let’s see how we can create a global event bus in vue.

In your main.js file, lets start by defining a global event bus as follows:

Vue.prototype.$eventHub = new Vue(); // Global event bus
new Vue({
el: '#app',
router: Router,
template: '<App/>',
store: store,
});

In this way, you do not have to export the event bus in each components.

Now, from any component, you can access and emit an event to the bus as follows:

methods: {
login(){
// login logic
// on success
this.$eventHub.$emit('logged-in');
  }
}

Now, in the other component, you need to listen to the event and add handlers for them. It has to be done in the “created” life hook of vue instance. Also, you need to make sure that the event listener is turned off before you destroy the component.

data(){
return {
//data
}
},
created() {
this.$eventHub.$on('logged-in', this.getCurrentUser);
},
beforeDestroy() {
this.$eventHub.$off('logged-in');
},
methods: {
getCurrentUser(){
     // Get current user information
}
}

This event bus can be listened from any component in your application and the handlers can be assigned to perform any actions based on the event emitted.

I’ll show you another example:

<!--name.vue-->

<template>
<div>
<h1>Hello World, I'm {{ name }}</h1>
</div>
</template>

<script>
export default{
data(){
return {
name: 'Foo'
}
},

created() {
this.$eventHub.$on('change-name', this.changeName)
},

beforeDestroy(){
this.$eventHub.$off('change-name');
},

methods: {

changeName(name)
{
// name will be automatically transported to the parameter.
this.name = name;
}

}
}
</script>

Second component:

<!--change-name.vue-->
<template>
<div>
<input type="text" v-model="newName">
<button @click.prevent="changeName()"></button>
</div>
</template>
<script>
export default{
data(){
return {
newName: ''
}
},

methods: {
changeName()
{
this.$eventHub.$emit('change-name', this.newName);
}
}
}
</script>

In this example, when you type and press the button, an event is emitted in to the global bus. A listener from the first component listen for the event and changes the name with the new name typed.

If you have any question or doubts, feel free to ask here at the comments and I can update the article or try to give you the solutions.

Update

You should be careful when using global event handlers. It might not be ideal for all cases. Lets imagine you’ve a widget which open a dynamic form upon a button click. If you have a list of such widgets on the same page, the global event listener might trigger on all widgets at the same time and it causes all widgets to show the dynamic form at the same time. So in such cases, try to use child-parent emits.

VueConfTO 2018 | 14–16 November 2018 | Fairmont Royal York Toronto

VueJobs.com

If you are a Vue.js developer and looking for a job, subscribe to our mailing list. Or if you are looking for a Vue.js developer, feel free to post your job requirements here in vuejobs.com.

VueJobs.com