跳到主内容

Vue.js 3 如何使用Event Bus

· 2分钟阅读

How to create Event Bus in Vue 3?

tags: [faq]

In Vue 2, it was:

export const bus = new Vue();
bus.$on(...)
bus.$emit(...)

tags: [faq]

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 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 className="sidebar" :className="{'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()
...
}
...
}