如何基于ES module实现一个简单的自定义事件(ts版本)

338 阅读1分钟

如何基于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 对应实例嵌套一层引用即可