Vue3 实现Event-Bus事件总线 (mitt插件)
Vue3 没有像Vue2那样创建一个Vue实例作为事件传递的对象( 参考。两个属性下面引入的自定义的声明文件。
·
一、参考
二、问题描述
Vue3 没有像Vue2那样创建一个Vue实例作为事件传递的对象( 参考Vue2.x eventBus全局管理事件的“订阅/发布”),因此需要借助 mitt 插件来实现
三、开发案例
- 目录结构
- 定义
eventBus.ts
文件, 保证所有的引用都是同一个对象(单例)
import mitt, { Emitter } from 'mitt'
export const $Bus: Emitter = mitt()
export default $Bus
- 在 main.ts 文件中引用eventBus.ts,保证事件订阅是单例
mport { createApp } from 'vue'
import { Emitter } from 'mitt' // 用于 EventBus
import App from './App.vue'
const app = createApp(App)
/* *********** 引入 vue-router 4 ************ */
import router from './router'
app.use(router) // 加载路由
/* *********** 引入 mitt ************ */
import $Bus from '@/utils/eventBus'
// 定义监听事件
$Bus.on('foo', (params) => {
console.log('params', params)
});
// 触发事件
$Bus.emit('foo', 42);
// 定义到全局
app.config.globalProperties.$Bus = $Bus
- 父组件监听事件
<template>
<busComp class=""></busComp>
<div>我是父组件 pageBus</div>
</template>
<!-- <script setup lang="ts">
// 这里vue组件的后缀要不从全了,如果省略,虽然vite 能够识别并正确展示,但是ts无法识别,导致编译器一直提示找不到模块
import busComp from '@/pages/vue3Advance/comp/busComp.vue';
import { getCurrentInstance, onMounted, onBeforeUnmount } from 'vue';
const instance = getCurrentInstance();
function handleBus(val: any) {
console.log('handleBus', val);
}
onMounted(() => {
instance?.proxy?.$Bus.on('on-btn-click', handleBus);
})
onBeforeUnmount(() => {
console.log('beforeUnmount')
instance?.proxy?.$Bus.off('on-btn-click', handleBus);
});
</script> -->
<script lang="ts">
import { defineComponent, ref, reactive, computed } from 'vue'
import busComp from '@/pages/vue3Advance/comp/busComp.vue'
export default defineComponent({
components: {
busComp
},
mounted: function () {
console.log('mounted')
this.$Bus.on('on-btn-click',this.handleBus)
},
beforeUnmount: function () {
console.log('beforeUnmount')
this.$Bus.off('on-btn-click',this.handleBus)
},
methods: {
handleBus (val: any) {
console.log('handleBus', val)
}
}
})
</script>
<style scoped lang="scss"></style>
- 子组件busComp.vue触发事件
<template>
<div class="">
<el-button type="primary" @click="emitEvent">触发mitt定义的bus</el-button>
</div>
</template>
<script setup lang="ts">
import {getCurrentInstance} from 'vue'
const instance= getCurrentInstance() // 获取组件实例,相当于配置选项的this
function emitEvent () {
instance?.proxy?.$Bus.emit('on-btn-click','我是mitt bus触发的事件')
}
</script>
<style scoped lang="scss">
</style>
typescript 解析 instance?.proxy?.$Bus出错?
- Vue3定义实例的声明类型文件,参考官网扩展全局属性
- 定义 tsconfig.json 指明声明文件的位置
{
"compilerOptions": {
"sourceMap": true,
"outDir": "./dist",
"rootDir": "./src",
"paths": {
"@/*": ["./src/*"] // 设置别名路径
},
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"moduleResolution": "Node",
"strict": true,
"jsx": "preserve",
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"lib": ["ESNext", "DOM"],
"skipLibCheck": true,
"types": ["./src/types/*.d.ts", "vite/client", "unplugin-icons/types/vue"],
"noEmit": true
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "src/router/dynamicAddRoutes.bad.ts"],
"references": [{ "path": "./tsconfig.node.json" }]
}
分别在 compilerOptions.types 和 include 两个属性下面引入的自定义的声明文件
更多推荐
所有评论(0)