vue3集成Mitt发布订阅库

先从git上扒来一段话介绍一下mitt这个库:

Mitt是一个小巧的JavaScript发布-订阅库,用于在应用程序中实现事件监听和触发。

它只有70行代码,并支持ES模块、CommonJS和UMD等多种模块化规范。使用Mitt,您可以轻松地将消息传递给订阅者,从而实现组件之间的通信和功能扩展。该库非常灵活且易于使用,可帮助您优化项目的结构和性能。

在项目开发中经常会遇到组件之间互相通信,如父子兄弟之间。之前一直用$emit绑定方法,很麻烦而且还有局限性。然而mitt提供的发布订阅模式,可以全局监听并且使用简洁易懂。

介绍一下它的几个方法:

  • on:订阅一个事件。

  • off:根据给定的名称,取消订阅事件。

  • emit:触发订阅事件的方法。

下面进入实战:

1.先安装一下mitt

npm install -S mitt

2. 在src下创建plugins目录,并新建mybus.js,然后按照如下进行实例化导出

import mitt from 'mitt'
export default mitt()

3. 在进行发布订阅的组件中导入mitt,主要就是send方法中的

mitt.emit("fun", {

data:"data"

});

第一个参数是发布事件名称,第二个参数是要发布的数据。

解释一下我为什么这里用了setTimeout。因为有的业务场景,目标组件是不显示的,此时v-if=false,所以目标组件就无法监听订阅事件。

所以这里分开执行,当我需要发布的时候,先把组件显示出来,然后再进行事件发布。

<template>
    <h2>组件A</h2>
    <button @click="send">发送消息</button>
    <B v-if="show"></B>
</template>
import {reactive, toRefs, watch, getCurrentInstance, onMounted} from "vue"
import mitt from "@/plugins/mybus"
import B from '@/views/b.vue'
export default {
    name: "a",
    components:{
        B
    },
    setup(props, {emit}) {
      const state = reactive({
        show:false
      })
      const send = ()=>{
        state.show=true;
        setTimeout(function(){
            mitt.emit("fun", {
                data:"data"
            });
        })
      }
      onMounted(() => {
        
      })
      return {
        ...toRefs(state),send
      }
    }
  }

4. 目标组件进行订阅,这里的监听主要就是

mitt.on('fun',(data)=>{

console.log("B接收到A的数据:",data)

});

使用mitt的on方法来订阅事件,第一个参数是事件名称,第二个参数是回调方法,回调参数就是发布的数据

import {reactive, toRefs, watch, getCurrentInstance, onMounted} from "vue"
import mitt from "@/plugins/mybus"
export default {
    name: "b",
    setup(props, {emit}) {
      onMounted(() => {
        mitt.on('fun',(data)=>{
            console.log("B接收到A的数据:",data)
        });
      })
    }
  }

我想大部分同志都是为了解决问题才看到的这篇文章,为了不占用感情,所以把原理解析放到了最后

可以看下源码

function mitt(all) {
    // 声明一个Map类型,作为整体事件处理中心
    all = all || new Map();
    return {
        all,
        on (type, handler) {
            // 先获取是否有对应事件的处理函数数组
            let handlers = all.get(type);
            if (handlers) {
                // 将新注册的函数推送到对应时间的函数数组中
                handlers.push(handler);
            }
            else {
                // 创建一个对应 type 的函数数组
                all.set(type, [handler]);
            }
        },
        off (type, handler) {
            // 从map中取出所有的对应的函数数组
            let handlers = all.get(type);
            if (handlers) {
                // 如果存在hanlder,进行筛选后,从数组中删除。
                // 如果不存在直接清空当前事件所有的处理函数
                if (handler) {
                    handlers.splice(handlers.indexOf(handler) >>> 0, 1);
                }
                else {
                    all.set(type, []);
                }
            }
        },
        emit (type, evt) {
            let handlers = all.get(type);
            // 按照取出的函数数组遍历循环执行
            if (handlers) {
                handlers
                    .slice()
                    .map((handler) => {
                        handler(evt);
                    });
            }
            // 如果注册了 "*" 的事件,执行它
            handlers = all.get('*');
            if (handlers) {
                handlers
                    .slice()
                    .map((handler) => {
                        handler(type, evt);
                    });
            }
        }
    };
}
exports.default = mitt;

其实核心思想就是用一个map来储存事件,订阅的时候根据key来找到对应的方法。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值