Vue.js Global Event Store

2017-01-08 Vue.js JavaScript Plugin

A common issue I see coming up with new frameworks like Vue.js is the event system. Should it use some kind of $dispatch and $broadcast system or only allow communication between parent/child directly.

Personally I like the more restricted direction Vue.js has taken in Vue 2. We can only talk directly from the child up to the parent. This is good for plugin development allowing an easy way for child components to talk to their parents. Other than this we don't really need an event system at all.

Since I started using Vue 1.x I've always used my own little event plugin.

It's less than 50 lines of code and can easily be tossed into any project. I keep it handy on github and you can also get it through npm

module.exports = (function () {

    function Event() {
        this.data = {};
    }

    Event.prototype.on = function (name, func) {
        if (this.$event.data[name]) {
            console.error('Vue Event: The event ' + name + ' already exists!.');
            return;
        }

        this.$event.data[name] = func.bind(this);
    };

    Event.prototype.off = function (name) {
        if (this.data[name]) {
            delete this.data[name];
        }
    };

    Event.prototype.emit = function (name, data) {
        if ( ! this.data[name]) {
            console.error('Vue Event: The event ' + name + ' does not exist!.');
            return;
        }

        this.data[name](data);
    }

    return function install(Vue) {
        var event = new Event,
            on = event.on;

        Object.defineProperties(Vue.prototype, {
            $event: {
                get: function() {
                    event.on = on.bind(this);

                    return event;
                }
            }
        });
    }
})();

We can now set our events globally through the event store.

this.$event.on('account:reset', function (data) {});

this.$event.emit('account:reset', {some: 'data'});

this.$event.off('account:reset');

The plugin also includes an error check for duplicate naming in case we mess up or forget to destroy an event.

this.$event.on('account:reset');

this.$event.on('account:reset'); // Will produce error.

Now we can set and create events in our own private event instance without worrying about any conflicts.

I like keeping my app super light and find that even a global store or Vuex just adds confusion and more code that's really unnecessary. This is the beauty of using Vue.js. It's so light weight we can just role our own little private stores. In fact I use one for pretty much all my components. For instance I have component with a little store for modals (vue-element). This allows me to fire off things like $modal.show('product-delete');.

Related Posts