在Vue3+TypeScript 前端项目中使用事件总线Mitt 您所在的位置:网站首页 vue支持typescript 在Vue3+TypeScript 前端项目中使用事件总线Mitt

在Vue3+TypeScript 前端项目中使用事件总线Mitt

#在Vue3+TypeScript 前端项目中使用事件总线Mitt| 来源: 网络整理| 查看: 265

import mitt from 'mitt' const emitter = mitt() // 订阅一个具体的事件 emitter.on('foo', e => console.log('foo', e) ) // 订阅所有事件 emitter.on('*', (type, e) => console.log(type, e) ) // 发布一个事件 emitter.emit('foo', { a: 'b' }) // 根据订阅的函数来取消订阅 function onFoo() {} emitter.on('foo', onFoo) // listen emitter.off('foo', onFoo) // unlisten // 只传一个参数,取消订阅同名事件 emitter.off('foo') // unlisten // 取消所有事件 emitter.all.clear()

而我们如果在Vue3 + TypeScript 环境中使用的话,就需要类型化事件的类型,已达到强类型的处理目的。

import mitt from "mitt"; type Events = { foo: string; bar: number; }; // 提供泛型参数让 emitter 能自动推断参数类型 const emitter = mitt(); // 'e' 被推断为string类型 emitter.on("foo", (e) => { console.log(e); }); // ts error: 类型 string 的参数不能赋值给类型 'number' 的参数 emitter.emit("bar", "xx"); // ts error: otherEvent 不存在与 Events 的key中 emitter.on("otherEvent", () => { // });

在前端项目使用的时候,我们在utils/mitt.ts中定义默认导出的mitt对象,如下代码所示。

// utils/mitt.ts import mitt, { Emitter } from 'mitt'; // 类型 const emitter: Emitter = mitt(); // 导出 export default emitter;

在其中的MittType类型,可以单独文件放置TypeScript的预定义文件目录中,如types/mitt.d.ts

而我们在使用的时候,直接导入该对象就可以了,如下代码所示。

declare type MittType = { openSetingsDrawer?: string; restoreDefault?: string; setSendColumnsChildren: T; .................. //省略其他事件类型 noticeRead: number; // 消息已读事件 lastAddParentId?: string | number;//新增记住最后的父信息 };

例如我们定义一个更新和记住父菜单的Mitt 事件,在页面加载完毕的时候监听事件,在页面退出的时候关闭事件即可,如下代码所示是在菜单列表页面中处理的。

import { onMounted, onUnmounted, reactive, ref } from 'vue'; import mittBus from '/@/utils/mitt'; ...... onMounted(async () => { handleQuery(); mittBus.on('submitRefresh', () => { handleQuery(); }); mittBus.on('lastAddParentId', (pid) => { state.lastAddParentId = pid as string;//记住最后的父菜单ID }); }); onUnmounted(() => { mittBus.off('submitRefresh'); mittBus.off('lastAddParentId'); });

在新增菜单的时候我们触发对应刷新事件 submitRefresh,以及触发选择的父记录ID的事件 lastAddParentId,这样就可以做相应的处理了。

例如在菜单的编辑子控件页面中,我们触发对应的事件逻辑代码如下所示。

// 关闭弹窗 const closeDialog = () => { mittBus.emit('submitRefresh'); state.isShowDialog = false; }; // 提交 const submit = () => { ruleFormRef.value.validate(async (valid: boolean) => { if (!valid) return; if (state.ruleForm.id != undefined && state.ruleForm.id > 0) { await menuApi.update(state.ruleForm); } else { await menuApi.add(state.ruleForm); //记住最后的菜单 mittBus.emit('lastAddParentId', state.ruleForm.pid); } closeDialog(); }); };

 如果为了减少每次重复的导入mitt,也可以把它全局挂载到变量中,统一入口进行访问,详细可以参考随笔《在基于vue-next-admin的Vue3+TypeScript前端项目中,为了使用方便全局挂载的对象接口》处理即可。

const $u: $u_interface = { message, test, util, date, crypto, base64, $t: i18n.global.t, fun: commonFunction(), cloneDeep, debounce, throttle, mitt }; //安装$u组件到app上 import type { App } from 'vue'; export default { install(app: App) { // 挂载全局 app.config.globalProperties.$u = $u; } };

 

 

 



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有