vue3+ts中使用mitt跨组件通信报错:没有与此调用匹配的重载。handler: WildcardHandler<Record<EventType, unknown>>

报错内容如下图:
在这里插入图片描述
在这里插入图片描述

mitt代码的使用方式:

import { onMounted } from vue;
import mittBus from '@/utils/mittBus';

onMounted(() => {
  mittBus.on('getFlowTableRowDetail'/*自定义监听事件名称,相当于下面的foo*/, getFlowTableRowDetail);
});
interface LoadParams {
  date: string;
  dataId: string;
}
function getFlowTableRowDetail(data: LoadParams){/* 省略内容 */}

mittBus.js文件:

import mitt from "mitt";
const mittBus = mitt();
export default mittBus;

经过多方资料查阅,总结出问题出现的原因是ts中的类型推断异常。mittBus的参数无法推断出来。

如果使用的是最新的mitt@3.0.0版本,在ts中使用mitt时需要添加类型注解,去官网查阅使用方式如下:

Usage

1、Set “strict”: true in your tsconfig.json to get improved type inference for mitt instance methods.

import mitt from 'mitt';

type Events = {
  foo: string;
  bar?: number;
};
// inferred as Emitter<Events>  // 推断为发射器<事件>
const emitter = mitt<Events>();

// 'e' has inferred type 'string'  // “e”具有推断的类型“string”
emitter.on('foo', (e) => {});

// Error: Argument of type 'number' is not assignable to parameter of type 'string'. (2345)  // 错误:类型为“number”的参数不能分配给类型为“string”的参数。(2345)
emitter.emit('foo', 42); 

2、Alternatively, you can use the provided Emitter type:

import mitt, { Emitter } from 'mitt';

type Events = {
  foo: string;
  bar?: number;
};

const emitter: Emitter<Events> = mitt<Events>();

这里我使用了第二种,mitt提供的Emitter类型。

官方示例里面因为使用的事件名称是固定的:foobar。但是我的代码里面事件名称是自定义的,所以此处不能直接写死,故使用一个字符串索引签名,这样事件名称可以自定义。如:我的项目代码中的事件名称自定义为getFlowTableRowDetail

修改mittBus.js文件代码如下:

import mitt, { Emitter } from "mitt";

// 定义类型别名,因全局使用并且需要自定义事件名称,所以使用索引签名定义内容
type Events = {
  [propName: string]: any;
};
// 提供泛型参数让 emitter 能自动推断参数类型
const mittBus: Emitter<Events> = mitt<Events>();
export default mittBus;

改完代码之后,类型推断异常消失,可以准确推断所需参数的类型了。
在这里插入图片描述
在这里插入图片描述

### 清除 Vue3 中通过 mitt 管理的所有事件 在 Vue3 应用中使用 `mitt` 进行组件间通信时,有时需要清除所有已注册的事件监听器。这可以通过访问 `mitt` 实例的方法来完成。 #### 访问并清空所有事件 为了确保当不再需要这些事件监听器时能够正确清理资源,在组件卸载阶段应当执行相应的操作: ```javascript import { onUnmounted } from &#39;vue&#39;; import mitt from &#39;mitt&#39;; const emitter = mitt(); // 注册事件处理程序... emitter.on(&#39;some-event&#39;, handler); onUnmounted(() => { // 方法一:逐个移除特定名称的事件监听器 emitter.off(&#39;some-event&#39;); // 或者方法二:一次性删除所有类型的监听器 Object.keys(emitter.all).forEach(eventType => { delete emitter.all[eventType]; }); }); ``` 需要注意的是,直接修改内部属性(如上述代码中的 `emitter.all` 对象)并不是官方推荐的做法[^3]。然而对于某些场景下确实存在这样的需求,则可以考虑这种方式作为临时解决方案直到找到更优雅的办法为止。 更好的实践是在设计之初就规划好如何管理不同生命周期内的订阅关系,并尽可能利用现有的 API 接口去控制它们的行为。 #### 官方API调用建议 理想情况下应该遵循库的设计意图,即只针对具体感兴趣的事件类型调用 `.off()` 方法来解除绑定。这样不仅保持了良好的编码习惯也减少了潜在的风险。 如果确实有业务逻辑上必须批量清除的需求,也可以尝试联系作者或社区寻求是否有更新版本提供了更加正式的支持。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值