2

I am creating a Vue 3 app and trying to implement a Global event bus for two components to communicate on. In past w/Vue 2 I would do the following:

import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
export const bus = new Vue();
new Vue({
  render: h => h(App),
}).$mount('#app')

Now w/Vue 3 I understand new Vue is out and createApp() is in. I thus setup bus as:

// main.js
import { createApp } from "vue";
import App from "./App.vue";

export const bus = createApp();

createApp(App).mount("#app");

And App.vue is:

<template>
  <!-- ============== Modal Component ============= -->
  <FormModal v-show="isModalVisible" @close="closeModal">
    <template v-slot:header> Add Equipment Item to Scrap List </template>
  </FormModal>

 
    <!-- More template stuff -->

  <DisplayScrap />
</template>

<script setup>
import { ref } from "vue";
import FormModal from "./components/form-modal.vue";
import DisplayScrap from "./components/display-scrap.vue";

Now when I go to the first component(The emitter) and try to import the Global bus :

// form.modal.vue
import { reactive, defineEmits, ref, toRaw } from "vue";
import addRow from "../helperFunctions/addRow.js";
import { bus } from "../main.js";

I now get error in console of:

Uncaught ReferenceError: can't access lexical declaration 'App' before initialization http://localhost:3000/src/main.js?t=1640126294730:7 main.js:7:1

Any advise on what is the proper way in Vue 3 to setup the global bus is most appreciated. Am I missing some circular reference that is causing the error? I don't see any example in the Docs for this type of situation...

Alan
  • 1,067
  • 1
  • 23
  • 37
  • Yes. I was trying to adapt a Vue 2 solution. But it looks like the whole $emit() and $on() macros have been eliminated in Vue 3. I was trying to avoid another dependency like mitt to my project. I don't know if that is possible now. – Alan Dec 21 '21 at 23:36
  • `$emit` actually is kept. they deleted `$on`, `$off` and `$once` – Tawfik Nasser Dec 21 '21 at 23:41
  • This question is answered in https://stackoverflow.com/questions/63471824/vue-js-3-event-bus – GeZo May 23 '22 at 08:05

2 Answers2

1
  • First the error:

    did you try to export const bus = createApp(); in a different file to avoid circular ref ?

  • Regarding global bus in vue3:

    it is recommended to use a global state like what vuex provide you or any external package as best practice to communicate between components.

    and even if you managed to import the created bus you still don't have the listener $on to receive the emitted data. as they deleted it in vue3

Tawfik Nasser
  • 1,018
  • 9
  • 17
  • 1
    Yes. I see in the Docs they deleted $on. Vuex seems like over kill. I just have one instance where two components need to exchange state. I was hoping to avoid another dependency. Thanks for your answer. – Alan Dec 22 '21 at 21:33
  • @Alan if this is the case. maybe implement your simple event emitter is what you are looking for ? look into some implementation here https://gist.github.com/mudge/5830382 – Tawfik Nasser Dec 22 '21 at 21:56
0

I have come across the same issue, and I found the vue3-eventbus to be the exact simple solution. It provides support for Vue2, Vue3, compositions API and also Typescript support. I rate this plugin highly.

Krishna Vedula
  • 1,643
  • 1
  • 27
  • 31