Vue.js - Create a global event bus

A VueJS quicktip

The event bus / publish-subscribe pattern, despite the bad press it sometimes gets, is still an excellent way of getting unrelated sections of your application to talk to each other. But wait! Before you go waste your time on another library, why not use Vue’s powerful built-in event bus?

Creating the event bus

The first thing you’ll need to do is create the event bus and make the bus available to each Vue instance by defining them on the prototype.

1
2
3
4
5
Object.defineProperty(Vue.prototype, '$bus', {
  get () {
    return this.$root.bus
  }
})

In your Vue component where you want to receive on the $bus put the following code. This listens to incoming requests send over the event bus.

1
2
3
4
5
6

  mounted () {
    this.$bus.$on('funcName', data => {
      // do something
    })
  }

To trigger the defined event you simply use the following on any of your Vue components.

1
2

  this.$bus.$emit('funcName', data)

Use case

In the following example, I trigger the visibility of a button located next to my breadcrumbs. Depending on what page is shown I want to manipulate the button text and function it triggers.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Breadcrumbs.vue

<template>
  <div>
    <button v-if="button.visible" 
            @click="$bus.$emit(button.func, true)" 
            class="btn btn-info d-none d-lg-block m-l-15">
       <i class="fa fa-plus-circle"></i> {{ button.text }}
    </button>
  </div>
</template>

export default {
  name: 'Breadcrumbs',

  data () {
    return {
      pageTitle: this.$route.name,
      button: {
        visible: false,
        func: '',
        text: ''
      }
    }
  },

  mounted () {
    this.$bus.$on('breadButton', data => {
      this.button = data
    })
  }
}

Now you can trigger the button’s visibility and action from any of your Vue components.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12

export default {
  mounted () {
    ...
    this.$bus.$emit('breadButton', {
      visible: true, 
      text: 'New Package',
      func: 'showOrderPage'
    })
    ...
  }
}

In more complex cases, you should consider employing a dedicated state-management pattern. Full documentation

Licensed under CC BY-NC-SA 4.0
Last updated on Mar 26, 2018 00:00 UTC
Built with Hugo
Theme Stack designed by Jimmy