vue3集成Mitt发布订阅库
创始人
2025-05-29 00:54:12

先从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,所以目标组件就无法监听订阅事件。

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

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来找到对应的方法。

相关内容

热门资讯

最新消息“大宝江苏麻将有没有挂... 无需打开直接搜索微信【2832208】本司针对手游进行,选择我们的四大理由:大宝江苏麻将这款游戏其实...
玩家必看“随意玩拼三张能开透视... 您好:随意玩拼三张这款游戏可以开挂,确实是有挂的,需要了解加客服微信【6355786】很多玩家在随意...
最新消息新悟空有开挂辅助软件吗... 您好:新悟空这款游戏可以开挂,确实是有挂的,需要了解加客服微信【3354922】很多玩家在这款游戏中...
重大通报“铭心斗牛有透视挂吗”... 您好:铭心斗牛这款游戏可以开挂,确实是有挂的,需要软件加微信【5902455】,很多玩家在铭心斗牛这...
最新一款(新贝壳炸金花)真的有... 您好:新贝壳炸金花这款游戏可以开挂,确实是有挂的,需要了解加客服微信【6534989】或【915-8...