Tutorial

How To Create a Global Event Bus in Vue 2

Updated on March 24, 2021
author

Joshua Bemenderfer

How To Create a Global Event Bus in Vue 2

Introduction

The event bus / publish-subscribe pattern is a way of getting unrelated sections of your application to talk to each other.

The event system used in Vue components can be used in an event bus / publish-subscribe pattern.

Note: This tutorial is specific for Vue 2. In Vue 3, $on, $off, and $once have been removed. External libraries that provide this functionality are recommended.

In this article, you will apply Vue’s powerful built-in event bus.

Prerequisites

To complete this tutorial, you will need:

This tutorial was verified with Node v15.3.0, npm v6.14.9, and vue v2.6.11.

Step 1 — Setting Up The Project

For the purpose of this tutorial, you will build from a default Vue project generated with @vue/cli.

  1. npx @vue/cli create vue-event-bus-example --default

This will configure a new Vue project with default configurations: Vue 2, babel, eslint.

Navigate to the newly created project directory:

  1. cd vue-event-bus-example

You will need to create the event bus and export it somewhere so other modules and components can use it. First, create a new file. Import the Vue library. Then, export an instance of it.

src/event-bus.js
import Vue from 'vue';
export const EventBus = new Vue();

For this tutorial, the instance was set to the variable EventBus.

What you are essentially getting is a component that is entirely decoupled from the DOM or the rest of your app. All that exists on it are its instance methods.

Now that you have created the event bus, you will need to import it into your components and call the same methods that you would use if you were passing messages between parent and child components.

Next, let’s apply EventBus.$emit().

Step 2 — Sending Events

Consider a scenario with a component that notifies the entire app of how many times it has been clicked whenever someone clicks on it.

Note: This example uses a single-file-component here, but you can use whatever method of creating components you would like.

Here is how you would go about implementing that using EventBus.$emit(channel: string, payload1: any, ...):

src/components/ClickCountButton.vue
<template>
  <button @click="emitGlobalClickEvent()">{{ clickCount }}</button>
</template>

<script>
import { EventBus } from '@/event-bus';

export default {
  data() {
    return {
      clickCount: 0
    }
  },

  methods: {
    emitGlobalClickEvent() {
      this.clickCount++;
      EventBus.$emit('clicked', this.clickCount);
    }
  }
}
</script>

This code produces a button. Clicking on the button would send the event on a channel (clicked) with a payload (clickCount).

Modify App.vue to use this component.

src/App.vue
<template>
  <div id="app">
    <ClickCountButton></ClickCountButton>
  </div>
</template>

<script>
import ClickCountButton from './components/ClickCountButton'

export default {
  name: 'App',
  components: {
    ClickCountButton
  }
}
</script>

Next, let’s apply EventBus.$on.

Step 3 — Receiving Events

Now, any other part of your app can import the event bus and listen on the clicked channel using EventBus.$on(channel: string, callback(payload1,...)).

Apply this to your application by modifying App.vue:

src/App.vue
<script>
import { EventBus } from './event-bus';
import ClickCountButton from './components/ClickCountButton'

export default {
  name: 'App',
  components: {
    ClickCountButton
  }
}

const clickHandler = function(clickCount) {
  console.log(`The button has been clicked ${clickCount} times!`)
}

EventBus.$on('clicked', clickHandler);
</script>

This code creates an event listener for clicked and logs a message to the console with the number of times the button has been clicked.

Note: If you would only like to listen for the first emission of an event, you can use EventBus.$once(channel: string, callback(payload1,...)).

Next, let’s apply EventBus.$off.

Step 4 — Removing Event Listeners

You can unregister the handler from the clicked channel using EventBus.$off(channel: string, callback(payload1,...)).

Apply this to your application by modifying App.vue:

src/App.vue
<script>
import { EventBus } from './event-bus';
import ClickCountButton from './components/ClickCountButton'

export default {
  name: 'App',
  components: {
    ClickCountButton
  }
}

const clickHandler = function(clickCount) {
  console.log(`The button has been clicked ${clickCount} times!`)
}

EventBus.$on('clicked', clickHandler);

EventBus.$off('clicked', clickHandler);
</script>

By providing an event and a callback, EventBus.$off will only remove the listener for this specific callback.

Note: You could also remove all listeners for a particular event using EventBus.$off('clicked') with no callback argument.

And if you really need to remove every single listener from EventBus, regardless of channel, you can call EventBus.$off() with no arguments at all.

Now, you have utilized .$emit, .$on, and .$off.

Conclusion

In this tutorial, you used Vue’s powerful built-in event bus to listen for a clicked event and log a message with the click count. This was achieved by utilizing .$emit, .$on, and .$off.

If you’d like to learn more about Vue.js, check out our Vue.js topic page for exercises and programming projects.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar
Joshua Bemenderfer

author

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
2 Comments


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Why not just use $root rather than employing a whole new instance of vue? Is it not safe or something?

Thank you, this is great!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.