'Vue 3 Event Bus with Composition API

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
  }
} 


Solution 1:[1]

You may be able to use getCurrentInstance to get the global property

component:

import { getCurrentInstance } from 'vue';
export default {
  setup() {
    // get current instance
    const internalInstance = getCurrentInstance(); 
    // get the emitter from the instance
    const emitter = internalInstance.appContext.config.globalProperties.emitter;
  }
} 

Solution 2:[2]

So far I have used this code to make the "emitter" available.

//main.ts
import mitt from 'mitt'
const emitter = mitt()
export default emitter

And then inside the components I use

import emitter from '@/main';

This worked so far in Vue2 and Vue3 - at least with the options API.

I have to admit though that I currently run into some trouble with the new vite server and the hot module reload (hmr). Is this style suboptimal in any way?

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Daniel
Solution 2 Kez