Typescript重构事件机制

Typescript重写事件

基础版本

Emitter.ts
//类似于事件的Event
import EmitterTarget from "./EmitterTarget.js";

export default class Emitter{
    public type:string;
    public target:EmitterTarget|null=null;
    [key:string]:any;
    //暴露属性
    constructor(type:string){
        this.type=type;
        //把new Emitter("xxx")存入type属性中
    }
}
EmitterTarget.js
import Emitter from "./Emitter.js";
export interface IHandler{
    (e:Emitter):void
}
export interface IHandlerList{
    [key:string]:Array<IHandler|null>;
}
//定义两个接口
export default class EmitterTarget{
    private handlerList:IHandlerList={}
    //把传入的回调函数以type为key 回调函数名为value放入对象中
    constructor(){
    }
    //监听方法
    public addEventListener(type:string,handler:IHandler):void
    {
       if(!this.handlerList[type])this.handlerList[type]=[];
        //如果传入的监听的事件名没有的时 给对象中增加一个空数据放置回调函数
       if(this.handlerList[type].includes(handler)) return;
        //如果以该事件名的数组中有这个同样的回调函数跳出
       this.handlerList[type].push(handler);
        //如果都没有 把回调函数push到数组中
    //    console.log(this.handlerList);
    }
    //移除方法
    public removeEventListener(type:string,handler:IHandler):void
    {
        if(!this.handlerList[type] || !this.handlerList[type].includes(handler)) return;
        //如果handlerList对象中没有这个事件,或者这个事件中没有这个回调函数跳出
        var index=this.handlerList[type].indexOf(handler);
        //找到对应索引
        this.handlerList[type][index]=null;
        //赋值为null 注意点数组塌陷问题。之后可以有优化
    }
    //主动抛发方法
    public dispatchEvent(evt:Emitter):void
    {
    //   console.log(evt.type);
        if(!this.handlerList[evt.type]) return;
        //如果没有这个事件名跳出
        var arr:Array<IHandler|null>=this.handlerList[evt.type];
        for(var i=0;i<arr.length;i++){
            var fn:IHandler|null=arr[i];
            if(fn) fn.call(this,evt);
            //改变this指向
        }
        for(var j=0;j<arr.length;j++){
            if(!arr[j]){
                arr.splice(j,1);
                j--;
                //删除对应的事件 并且-- 如果不会数组塌陷
            }
        }
    }
}
测试代码
import Emitter from "./Emitter.js";
import EmitterTarget from "./EmitterTarget.js";

var target:EmitterTarget=new EmitterTarget();
target.addEventListener("a",aHandler);
target.addEventListener("a",aHandler1);
target.addEventListener("a",aHandler1);
target.addEventListener("a",aHandler2);

target.addEventListener("b",aHandler3);
target.addEventListener("b",aHandler1);

var evt:Emitter=new Emitter("a");
evt.a=1;
target.dispatchEvent(evt);

var evt:Emitter=new Emitter("a");
target.dispatchEvent(evt);

function aHandler(e:Emitter):void
{
    // console.log(e.target)
    console.log(e,"handler")
}
// ts中使用this时,参数需要在第一个参数前面增加this:void指出this的类型
// 如果要调用这个this的方法时,那么this必须设置为这个函数中的this类型
function aHandler1(this:EmitterTarget,e:Emitter){
    console.log(e,"handler1",this);
    this.removeEventListener("a",aHandler1);
}
function aHandler2(e:Emitter){
    console.log(e,"handler2")
}

function aHandler3(this:EmitterTarget,e:Emitter){
    console.log(e,"handler3",this)
}

优化版本

Emitter.ts

与上文一样

EmitterTarget.js

大体逻辑同上

import Emitter from "./Emitter.js";
export interface IHandler{
    (e:Emitter):void
}
export default class EmitterTarget{
    //考虑到Map结构松散不会有数组塌陷问题,且Set不会重复添加,使用到Map Set组合
    private handlerList:Map<string,Set<IHandler>>=new Map();
    constructor(){

    }
    public addEventListener(type:string,handler:IHandler):void
    {
        if(!this.handlerList.has(type)) this.handlerList.set(type,new Set<IHandler>());
        this.handlerList.get(type)?.add(handler);
    }
    public removeEventListener(type:string,handler:IHandler):void
    {
       if(!this.handlerList.has(type)) return;
       this.handlerList.get(type)?.delete(handler);
    }
    public dispatchEvent(evt:Emitter):void
    {
        if(!this.handlerList.has(evt.type)) return;
        evt.target=this;
        this.handlerList.get(evt.type)?.forEach((item:IHandler)=>{
            item.call(this,evt);
        })
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值