The question is published on by Tutorial Guruji team.
How to create Event Bus in Vue 3?
In Vue 2, it was:
export const bus = new Vue();
bus.$on(...) bus.$emit(...)
In Vue 3, Vue
is not a constructor anymore, and Vue.createApp({});
returns an object that has no $on
and $emit
methods.
Answer
As suggested in official docs you could use mitt library to dispatch events between components, let suppose that we a sidebar and header
which contains a button that close/open the sidebar and we need that button to toggle some property inside the sidebar component :
in main.js import that library and create an instance of that emitter and define as a global property:
Installation :
npm install --save mitt
Usage :
import { createApp } from 'vue' import App from './App.vue' import mitt from 'mitt'; const emitter = mitt(); const app = createApp(App); app.config.globalProperties.emitter = emitter; app.mount('#app');
in header emit the toggle-sidebar
event with some payload :
<template> <header> <button @click="toggleSidebar"/>toggle</button> </header> </template> <script > export default { data() { return { sidebarOpen: true }; }, methods: { toggleSidebar() { this.sidebarOpen = !this.sidebarOpen; this.emitter.emit("toggle-sidebar", this.sidebarOpen); } } }; </script>
In sidebar receive the event with the payload:
<template> <aside class="sidebar" :class="{'sidebar--toggled': !isOpen}"> .... </aside> </template> <script> export default { name: "sidebar", data() { return { isOpen: true }; }, mounted() { this.emitter.on("toggle-sidebar", isOpen => { this.isOpen = isOpen; }); } }; </script>
For those using composition api they could use emitter
as follows :
Create a file src/composables/useEmitter.js
import { getCurrentInstance } from 'vue' export default function useEmitter() { const internalInstance = getCurrentInstance(); const emitter = internalInstance.appContext.config.globalProperties.emitter; return emitter; }
And from there on you can use useEmitter
just like you would with useRouter
:
import useEmitter from '@/composables/useEmitter' export default { setup() { const emitter = useEmitter() ... } ... }