DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • What Is API-First?
  • Exploring Intercooler.js: Simplify AJAX With HTML Attributes
  • Microservices With .NET Core: Building Scalable and Resilient Applications
  • React, Angular, and Vue.js: What’s the Technical Difference?

Trending

  • Event-Driven Microservices: How Kafka and RabbitMQ Power Scalable Systems
  • Distributed Consensus: Paxos vs. Raft and Modern Implementations
  • After 9 Years, Microsoft Fulfills This Windows Feature Request
  • Introduction to Retrieval Augmented Generation (RAG)
  1. DZone
  2. Coding
  3. JavaScript
  4. Why and How To Create an Event Bus in Vue.js 3

Why and How To Create an Event Bus in Vue.js 3

In this article, readers will learn how to migrate their applications from Vue.js 2 to Vue.js 3, components communications of Vue.js, and Vue.js’ global state.

By 
Valerio Barbera user avatar
Valerio Barbera
·
Feb. 28, 23 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
8.0K Views

Join the DZone community and get the full member experience.

Join For Free

Since I’m working on the 2.0 version of my product’s UI (to be released in May), I’m publishing some technical tricks I learned from migrating my application from Vue.js 2 to Vue.js 3.

The current version of the Inspector frontend application uses a global event bus. It’s needed to make the root component of the application (App.vue) aware of some particular events fired inside the component chain.

Before going into the details of this specific implementation, let me describe the principles of components communication in Vue.js and why we decided to use a global event bus even if this is a not recommended practice.

Vue.js Components Communication

In Vue.js, each component is responsible to render a piece of UI users are interacting with. Sometimes, components are self-sufficient. They can retrieve data directly from the backend APIs. More often, a component is a child of a more structured view that needs to pass data to child components to render a specific part of the UI.

Components

Components can expose props to their parents. Props are the data a component needs from a parent to make it work. 

In the example below, the component needs the user object to render its name with different styles based on its role:

JavaScript
 
<template>
    <span :class="{'text-danger': user.is_admin}">
        {{user.first_name}} {{user.last_name}}
    </span>
</template>

<script>
export default {
    props: {
        user: {
            type: Object,
            required: true
	}
    }
}
</script>


This strategy enforces reusability, promotes maintainability, and is the best practice.

But, this works only for components with a direct relation in the tree, like a Menu.vue component that uses the User.vue component to show the user name:

JavaScript
 
<template>
    <div class="menu">
        <a href="#" class="menu-item">
            Home
        </a>

        <a href="/user" class="menu-item">
            <User :user="user"/>
        </a>
    </div>
</template>

<script>
export default {
    data() {
        return {
            user: {}
        };
    },

    created() {
        axios.get('/api/user').then(res => this.user = res.data);
    }
}
</script>


How Can Unrelated Components Communicate?

Vue.js Global State

There are two ways of making unrelated components communicate with each other:

  1. Vuex
  2. Event Bus

Vuex is a state management library. At first glance, it seems complicated, and in fact, it is a bit. You can use Vuex to store data that should be used globally in your app. Vuex provides you with a solid API to apply changes to this data and reflect them in all child components that use the Vuex data store.

Event bus is related to the classic Events/Listeners architecture. You fire an event that will be treated by a listener function if there is one registered for that event.

98% of the stuff in your typical app is not a function but really a state. So, you should use Vuex for everything as a default and drop back to an Event Bus when Vuex becomes a hurdle.

Event Bus Use Case: Our Scenario

I have come across a scenario where I need to run a function, not manage a state. So, Vuex doesn’t provide the right solution.

In Inspector, the link to access the form for creating a new project is spread over several parts of the application. When the project is successfully created, the application should immediately redirect to the installation instruction page. No matter where you are in the application, we must push the new route in the router to force navigation:

JavaScript
 
(project) => {
    this.$router.push({
        name: 'projects.monitoring',
        params: {
            id: project.id
        }
    });
};


How To Create an Event Bus in Vue3

Vue 2 has an internal event bus by default. It exposes the $emit() and $on() methods to fire and listen for events. 

So, you could use an instance of Vue as an event bus:

JavaScript
 
export const bus = new Vue();


In Vue 3, Vue is not a constructor anymore, and Vue.createApp({}); returns an object that has no $on and $emit methods.

As suggested in official docs, you could use the mitt library to dispatch events across components.

First, install mitt:

Shell
 
npm install --save mitt


Next, I created a Vue plugin to make a mitt instance available inside the app: 

JavaScript
 
import mitt from 'mitt';


export default {
    install: (app, options) => {
        app.config.globalProperties.$eventBus = mitt();
    }
}


This plugin simply adds the $eventBus global property to the Vue instance so we can use it in every component calling this.$eventBus.

Use the plugin in your app instance:

JavaScript
 
import { createApp } from 'vue';
const app = createApp({});

import eventBus from './Plugins/event-bus';
app.use(eventBus);


Now, we can fire the event “project-created” from the project form to fire the function defined in the App.vue component:

JavaScript
 
this.$eventBus.emit('project-created', project);


The global listener is placed in the root component of the app (App.vue):

JavaScript
 
export default {
    created() {
        this.$eventBus.on('project-created', (project) => {
            this.$router.push({
                name: 'projects.monitoring',
                params: {
                    id: project.id
                }
            });
        });
    }
}


Conclusion

By now, you should have a better understanding of migrating from Vue.js 2 to Vue.js 3, Vue.js component communications, and the Vue.js global state. I hope this article will help you make better decisions for the design of your application.

API Data store JavaScript UI Use case Vue.js Data (computing) Event Architecture Library Maintainability Reusability shell Tree (data structure)

Published at DZone with permission of Valerio Barbera. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • What Is API-First?
  • Exploring Intercooler.js: Simplify AJAX With HTML Attributes
  • Microservices With .NET Core: Building Scalable and Resilient Applications
  • React, Angular, and Vue.js: What’s the Technical Difference?

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!