7
votes

In my VueJS app I have a Vue instance which I'm using as an event bus for sending data between components.

It's just this:

import Vue from 'vue';
export const EventBus = new Vue();

Then in my components I import EventBus and use EventBus.$emit() and EventBus.$on().

This approach is explained here: https://alligator.io/vuejs/global-event-bus/

What I'd like to be able to do is listen to any event that is sent through EventBus. If I could bind one listener to all events I could use this for logging or to feed data into some system for my development environment that would show me all data as it went into eventBus, which would be super useful.

Is there any type of vm.$listenToEverything() that I'm missing or some way to make this work?

2
That is not possible, but you can always modify Vue.prototype.$emit to your own liking...Terry
You might find Vuex gives you a better overall solution than a global event bus.David L
Yes as davidL said try vuex which provides a centralized state mabagement which provides you getters which can be accessed anywhere in your appVamsi Krishna

2 Answers

5
votes

If you're in an ES6 context, you could take either of below approaches. I explain through comments.

Override through inheritance

'use strict'

import Vue from 'vue'

export class EventBus extends Vue {
  // Register a custom callback as meddler that gets called upon each event emission.
  // It can be bound to $on as well. 
  $meddle (callback) {
    this.meddler = callback
  }

  // Override Vue's $emit to call the custom meddler callback upon each event emission.
  $emit (event, ...args) {
    if (this.meddler && typeof this.meddler.call === 'function') {
      this.meddler(event, ...args)
    }

    return super.$emit(event, ...args)
  }

  // We can also override $on() to listen to callbacks being registered.
}

export default new EventBus()

Override through hijacking

Or using a "hijacking" factory class in case you don't want your Vue event bus to be wrapped. The logic is basically the same, however, in this approach we hijack, or in other words, monkey patch the methods instead of overriding them directly.

'use strict'

import Vue from 'vue'

class EventBusFactory {
  static create () {
    return this.hijack(new Vue())
  }

  static hijack (bus) {
    bus.$meddle = callback => {
      bus.meddler = callback
    }

    const orig$emit = bus.$emit
    bus.$emit = (event, ...args) => {
      if (bus.meddler && typeof bus.meddler.call === 'function') {
        bus.meddler(event, ...args)
      }

      orig$emit.call(bus, event, ...args)
    }

    return bus
  }
}

export default EventBusFactory.create()
2
votes

The author of VueJS provided a hacky solution for listening to all events:

var oldEmit = this.compiler.emitter.emit
this.compiler.emitter.emit = function () {
    console.log('got event: ' + arguments[0])
    oldEmit.apply(this, arguments)
}

Another solution (which is said to also work on v1.0):

const old_on = this.$on;
this.$on = (...args) => {
  // custom logic here like pushing to a callback array or something
  old_on.apply(this, args);
};