I have setup mitt and trying to dispatch event to another component but I am having hard time because in the setup()
method it doesn’t have this
for accessing app instance.
Here is what I tried:
import App from './App.vue' const el = document.getElementById('app') import mitt from 'mitt'; const emitter = mitt(); const app = createApp(App) app.config.globalProperties.emitter = emitter; app.mount(el);
And in the component, I want to dispatch an event
export default { setup() { function toggleSidebar() { this.emitter.emit('toggle-sidebar'); console.log(this); // binds to setup(), not the vue instance. } } }
As this
doesn’t exist, I can’t access the .emitter
. What am I missing? How to use officially suggested mitt in Vue 3 composition api?
By the way if I use the v2 syntax, I can access this.emitter
. But I am curious about Composition API way
export default { mounted() { console.log(this.emitter); // works } }
Advertisement
Answer
To use an event bus in Vue 3 Composition API, use Vue 3’s new provide
api in main.js, and then inject
in any component:
1. Install mitt:
npm install mitt
2. Provide:
main.js
import { createApp } from 'vue'; import App from './App.vue'; import mitt from 'mitt'; // Import mitt const emitter = mitt(); // Initialize mitt const app = createApp(App); app.provide('emitter', emitter); // ✅ Provide as `emitter` app.mount('#app');
3. Inject
3a. Any Component – Emit an event
import { inject } from 'vue' export default { setup() { const emitter = inject('emitter'); // Inject `emitter` const mymethod = () => { emitter.emit('myevent', 100); }; return { mymethod } } }
Call mymethod
from a button click or something.
3b. Any Component – Listen for the event
import { inject } from 'vue' export default { setup() { const emitter = inject('emitter'); // Inject `emitter` emitter.on('myevent', (value) => { // *Listen* for event console.log('myevent received!', `value: ${value}`); }); }, }
Console
myevent received! value: 100