本文已整理到 Github,地址 👉 blog。
如果我的内容帮助到了您,欢迎点个 Star 🎉🎉🎉 鼓励鼓励 :) ~~
我希望我的内容可以帮助你。现在我专注于前端领域,但我也将分享我在有限的时间内看到和感受到的东西。
在 Vue2 中,创建 Event Bus 如下:
export const bus = new Vue()
- bus.$on(...)
- bus.$emit(...)
在 Vue3 中,Vue 不再是构造函数,而是 Vue.createApp({}) 返回一个没有 $on、$emit 和 $once 方法的对象。
根据官方文档 Vue 3 迁移指南所建议的,我们可以使用 mitt 或 tiny-emitter 库在组件之间调度事件。
这里我们使用 mitt,它的源码也很简单,👉 地址。
安装
pnpm i mitt
您也可以单独把代码拷贝一份到项目,代码量较少。
用法
与 Vue2 一样,封装为 myBus.js:
- import mitt from 'mitt'
- export default mitt()
或者,你也可以定义为全局变量:
- import { createApp } from 'vue'
- import App from './App.vue'
- import mitt from 'mitt'
-
- const app = createApp(App)
- app.config.globalProperties.emitter = mitt()
然后,封装一个 hooks:
- // src/hooks/useEmitter.js
- import { getCurrentInstance } from 'vue'
-
- export default function useEmitter() {
- const internalInstance = getCurrentInstance()
- const emitter = internalInstance.appContext.config.globalProperties.emitter
-
- return emitter
- }
当然,为了方便管理,你也可以在需要用到的地方单独引入 mitt。
示例
假设我们有一个 sidebar 和 header,其中包含一个关闭/打开侧栏的按钮,我们需要该按钮来切换侧边栏组件内的某些属性。
点击按钮发出 toggle-sidebar 带有一些 payload 的事件:
- <template>
- <button @click="toggleSidebar">toggle</button>
- </template>
- <script setup>
- import { ref } from 'vue'
- import useEmitter from '@/hooks/useEmitter'
-
- const sidebarOpen = ref(true)
- const emitter = useEmitter()
-
- const toggleSidebar = () => {
- sidebarOpen.value = !sidebarOpen.value
- emitter.emit('toggle-sidebar', sidebarOpen.value)
- }
- </script>
在侧边栏中接收带有 payload 的事件:
- <template>
- <aside class="sidebar" :class="{'sidebar--toggled': !isOpen}">
- {{ isOpen }}
- </aside>
- </template>
- <script setup>
- import { ref, onMounted } from 'vue'
- import useEmitter from '@/hooks/useEmitter'
-
- const isOpen = ref(true)
- const emitter = useEmitter()
-
- onMounted(() => {
- emitter.on('toggle-sidebar', (isOpen) => {
- isOpen.value = isOpen
- })
- })
- </script>
