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


    事件总线Mitt使用非常简单,本篇随笔介绍在Vue3+TypeScript 前端项目中使用的一些场景和思路。我们在Vue 的项目中,经常会通过emits 触发事件来通知组件或者页面进行相应的处理,不过我们使用事件总线Mitt来操作一些事件的处理,也是非常方便的。

    Mitt 的GitHub官网地址如下所示:https://github.com/developit/mitt, 它的安装和其他插件一样,我们不再赘述,只讲述它的如何使用。

    Mitt 具有以下优点:

    • 零依赖、体积超小,压缩后只有200b
    • 提供了完整的typescript支持,能自动推导出参数类型。
    • 基于闭包实现,没有烦人的this困扰。
    • 为浏览器编写但也支持其它javascript运行时,浏览器支持ie9+(需要引入Mappolyfill)。
    • 与框架无关,可以与任何框架搭配使用。
    Mitt 只是提供了几个简单的方法,如on,off, emit 等基础的几个函数。
    在JS中我们使用的话,不需要类型化事件的类型,如下代码所示。
    复制代码
    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 事件,在页面加载完毕的时候监听事件,在页面退出的时候关闭事件即可,如下代码所示是在菜单列表页面中处理的。

    复制代码
    复制代码

    在新增菜单的时候我们触发对应刷新事件 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;
      }
    };
    复制代码

     

     

     

  • 相关阅读:
    【原理揭秘】Vite 是怎么兼容老旧浏览器的?你以为仅仅依靠 Babel?
    【Flutter】Flutter学习笔记
    Python---break关键字对for...else结构的影响
    已解决:Python Error: IndentationError: expected an indented block 问题
    prosemirror error - Applying a mismatched transaction
    部署了HTTPS以后重新验证证书如何取消301跳转
    它把RabbitMQ的复杂全屏蔽了,我朋友用它后被老板一夜提拔为.NET架构师
    Shiro之授权&注解
    Spring Cloud框架(原生Hoxton版本与Spring Cloud Alibaba)基础入门篇 ---- 搭建环境
    Spring与Web环境集成
  • 原文地址:https://www.cnblogs.com/wuhuacong/p/17244470.html