cklmercer
3 years ago
64
7
Vue

Use a Global Event Bus

Posted 3 years ago by cklmercer

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!

Please sign in or create an account to participate in this conversation.