Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

cklmercer's avatar

Use a Global Event Bus

If you're anticipating Vue 2.0, or simply trying to catch an event on a sibling component, a global event bus can be a huge help.

What does that look like?

JavaScript

/*
 * By extending the Vue prototype with a new '$bus' property
 * we can easily access our global event bus from any child component.
 */
Object.defineProperty(Vue.prototype, '$bus', {
    get() {
        return this.$root.bus;
    }
});

/*
 * This first component will listen for an event to be fired by the bus.
 */
Vue.component('listens-for-event', {

    template: `<div>{{ msg }}</div>`,
    
    ready() {
        // Register event listener
        this.$bus.$on('specialEvent', event => {
            this.msg = event.msg;
            alert(event.alert);
            console.log(event);
        });
    },
    
    data() {
        return {
            msg: 'I am listening for an event.'
        }
    }

});

/*
 * This next component will be firing an event through the bus.
 * 
 * Note: In this example, there's one component firing an event
 *       and one component listening for an event. In reality, 
 *       any component is free to both fire & listen for any
 *       number of events at the same time, via the bus.
 */
Vue.component('fires-event', {

    template: `<div>{{ msg }}</div>`,

    ready() {
        // We're using setTimeout() to spoof an async call.
        setTimeout(() => {
            // emit the event and pass with it an object of "event data".
            this.$bus.$emit('specialEvent', {
                msg: 'This message came from the event.',
                alert: 'Alert! Alert! Alert!'
            });
        
            this.msg = 'I fired an event.'
        }, 2500);
    },
    
    data() {
        return {
            msg: 'I am getting ready to fire an event.'
        }
    }
});

// This empty Vue model will serve as our event bus.
var bus = new Vue({})

// Finally, let's create our $root Vue model.
new Vue({
    el: '#app',
    data: {
        bus: bus // Here we bind our event bus to our $root Vue model.
    }
});

HTML

<div id="app">
    <listens-for-event></listens-for-event>
    <fires-event></fires-event>
</div>

Fiddle

https://jsfiddle.net/g8Lqv0rx/10/

That's the gist of it! If you have any questions or feedback, please share!

0 likes
7 replies
neeravp's avatar

Pretty good way to prep for the Vue 2.0 release. Thanks for the implementation example. I was playing around with the implementation for my app and I noticed one thing that suppose The <listens-for-event> component is instantiated through v-if condition which evaluates to false when the event is emitted i.e. the <listens-for-event> component is not yet rendered (or is not present in the current scope) then subsequently when v-if evaluates to true and the component is rendered or instantiated (post the event being emitted), it is not able to catch the event through the listener.

//08:40:10   
<fires-event> /* emits an event */ </fires-event>  
<listens-for-event v-if="someCondition"></listens-for-event> //here someCondition = false, so it is not rendered  

//08:40:15  
someCondition=true;  
<listens-for-event v-if="someCondition"></listens-for-event> gets rendered, but is not able to catch the event and handle response  

//But if scenario is as under:  
//08:40:10  

<listens-for-event v-if="someCondition"></listens-for-event> //someDondition=true; so it gets rendered and is able to catch the event and respond    

<fires-event> /* emits an event */ </fires-event>    

Is this how it is supposed to work - that any component needs to be within the current scope (has been rendered) to catch any event which is emitted, if it is not rendered when an event is emitted later on when it gets rendered, it will not be able to catch and respond to any event fired/emitted before the component was rendered? Or am I doing something wrong?

cklmercer's avatar

That is very much intended. While v-if evaluates to false the component doesn't exist within the DOM.

If you us v-show instead then you can catch the event even though the component isn't visible.

Using v-show with the event bus is one way that you can create a modal component.

neeravp's avatar

Thanks for the response. I was trying to figure out a bug in my code . Now its clear that it is intended behavior.

1 like
Kriptic's avatar

You guys have no idea how happy I am to come across this, thank you!

1 like
aurawindsurfing's avatar

Anyone experienced any niticeble delays while using event bus?

1 like
jalasem's avatar

How do we implement in a .vue extension way?

Please or to participate in this conversation.