如何基于ESmode实现一个简单的自定义事件
我们在vue 中不少同学会使用到vue的自定义事件,但是在vue3中已经将全局的自定义的事件取消了,官方建议使用mity库来实现类似的功能,但是这个如果直接引用函数,因为实例的不同可能会有不必要的麻烦,以及在工程化开发中,因不同的人员开发,易发生代码混淆冲突的情况。所以今天给大家带来一个自己封装的自定义事件库。
- 先上代码
// 此代码是typescript 代码
// miit.ts
export type Handler<T = any> = (event?: T) => void;
export class Miit {
private evetObj: Map<string, Handler[]> = new Map();
// 处理
on(eventName: string, fn: (...data: any) => any) {
const eventFunList: Handler[] | undefined = this.evetObj.get(eventName)
if (eventFunList) {
eventFunList.push(fn)
this.evetObj.set(eventName, eventFunList);
} else {
this.evetObj.set(eventName, [fn])
}
}
// 执行指定函数
emit(eventName: string, arg: any) {
const fnCopy = this.evetObj.get(eventName);
if (fnCopy) {
//使用map的原因是防止原始数据被污染
fnCopy.slice().map((fn) => fn(arg));
} else {
console.error(`eventName-${eventName}中的函数为空,请请检查是否创建监听on函数`);
}
}
// 清除当前项
off(eventName: string, fn: Handler) {
const eventFunList = this.evetObj.get(eventName);
if (eventFunList) {
eventFunList.splice(eventFunList.indexOf(fn) >>> 0, 1);
// splice clone 一个数据
}
}
}
-
首先我们需要先了解一下 ES module 与 common.js 区别
-
es module 使用 es6 新增的模块管理规范
-
common.js 是在es6 提出之前由node.js 提出
-
本质区别在于 commonjs 是值的拷贝 而 es module 是值的引用
因此我们呢,利用引用的特性在只需要嵌套一次 es module 的引用即可实现全局引入,而避免命名冲突
-
const myMiit = new Miit();
myMiit.on(eventName,eventFunc);
myMiit.emit(eventName);
myMiit.off(eventName,eventFunc);
// 因为myMiit 的名不同所以各自并不 同一事件名 不同示例 相互不影响
graph TD
miit --> A引入miit库并创建实例 --> B引入A创建的实例并调用其中的方法
我们只需跟据需求new 对应实例嵌套一层引用即可