观察者模式,利用TypeScript简单重构Event

观察者模式,利用TypeScript简单重构Event

如果想给一个Box类的实例化对象添加事件侦听,正常来说,我们写一个Box类:

Box.ts

export default class Box extends EventTarget{
    //给Box设置一个静态只读字符串类型的事件类型变量
    static readonly EVENT_ID:string = "Box_event_id";
    //给一个私有属性
    private num:number = 2;
    constructor() {
        super();
    }

    dispatch():void{
        var evt:Event = new Event(Box.EVENT_ID)
        // evt.num = this.num; //如果evt是Event类型,会报错,因为Event没有num属性,
        // 也就意味着在事件抛发的时候不能带一些数据出去
        this.dispatchEvent(evt)
    }

}

然后再Main.ts中导入,创建实例化对象b:

import Box from "./Box";

var b:Box = new Box()
// 让实例化对象侦听Box.EVENT_ID事件,并执行eventHandler回调函数
b.addEventListener(Box.EVENT_ID, eventHandler);
//Box实例化对象抛发事件
b.dispatch();
function eventHandler(e:Event):void{
    console.log(e);
}

在执行页面后

<script src="require.js" data-main="./js/event/Main">script>

会这样报错:
在这里插入图片描述

因为EventTarget是一个Dom对象,而ts不属于Dom,如果以上写在js里是没有问题的,但是在ts里是无法运行的,所以我们可以简单重构下Event,可以完成简单的事件抛发侦听就可以了

新建一个事件类EmitterEvent,新建一个事件目标类EmitterTarget

EmitterEvent.ts

export default class EmitterEvent{
    //为了可以任意添加字符型属性
    [key:string]:any;
    //可以开放几个公有的事件属性,如target,currentTarget,为了简单就不加其他的属性了,而且必须只能是EmitterTarget类型因为只有EmitterTarget类型才能抛发和侦听事件
    public target?:EmitterTarget;
    public currentTarget?:EmitterTarget;
    public type?:string;
    //构造函数生成时将事件类型type带入,type是string类型
    constructor(type:string) {
        this.type = type;
}

EmitterTarget.ts


import EmitterEvent from "./EmitterEvent";
import IEventListener from "./IEventListener";
export default class EmitterTarget{
    //由于是先侦听后抛发,所以我们可以将事件类型和handler都保存起来,当我们dispatch的时候就激活这个函数
    //可以创建一个对象来保存
    // private eventDic:object = {}; //不能使用object类型,是因为object不能增加属性,会报错
    //为此我们新建一个接口IEventListener,让eventDic对应这个接口类型
    private eventDic:IEventListener = {};
    constructor() {

    }
    //提供事件抛发函数,public暴露
    public dispatchEvent(evt:EmitterEvent):void{
        //首先判断this.eventDic[evt.type as string]是否存在
        if(!evt.type) return;
        evt.currentTarget = this;
        evt.target = this;
        //console.log(evt)//EmitterEvent{type: "Box_event_id", num: 2}
        //this.eventDic[(evt.type as string)](evt);//evt.type在之前定义可能为空,所以给它断言为string
        //多个函数时,需要使用循环,
        if(!this.eventDic[evt.type]) return;
        for(var i = 0; i < this.eventDic[evt.type].length;i++){
            this.eventDic[evt.type][i](evt);
        }
    }
    //提供事件侦听函数,public暴露
    public addEventListener(type:string, handler:Function):void{
        //this.eventDic[type] = handler
        //console.log(this.eventDic)//Box_event_id: ƒ eventHandler(e)
        
    }
    //提供删除事件函数,public暴露
    public removeEventListener(type:string, handler:Function):void{
		if(!this.eventDic[type]) return;
        //数组长度为0,将数组释放掉,
        this.eventDic[type].length = 0;
    }
}

IEventListener.ts

export default interface IEventListener{
    //[key:string]:any;
    //函数的数组,为了可以一个事件绑定多个函数
    [key:string]:Array<Function>;
}

Box.ts

import EmitterEvent from "./EmitterEvent";
import EmitterTarget from "./EmitterTarget";
//现在Box应该继承的就不该是EventTarget了,应该是我们自己写的EmitterTarget类
export default class Box extends EmitterTarget{
// export default class Box extends EventTarget{
    //给Box设置一个静态只读字符串类型的事件类型变量
    static readonly EVENT_ID:string = "Box_event_id";
    //给一个私有属性
    private num:number = 2;
    constructor() {
        super();
    }

    dispatch():void{
        // var evt:Event = new Event(Box.EVENT_ID)
        // evt.num = this.num; //如果evt是Event类型,会报错,因为Event没有num属性,也就意味着在事件抛发的时候不能带一些数据出去
        var evt:EmitterEvent = new EmitterEvent(Box.EVENT_ID)
        evt.num = this.num;
		//this需要一个dispatchEvent()方法,那么就需要EmitterTarget提供一个
        this.dispatchEvent(evt)
    }

}

Main.ts

import Box from "./Box";
import EmitterEvent from "./EmitterEvent";

var b:Box = new Box()
// 让实例化对象侦听Box.EVENT_ID事件,并执行eventHandler回调函数
b.addEventListener(Box.EVENT_ID, eventHandler);
//侦听第二个
b.addEventListener(Box.EVENT_ID, eventHandler1);
//Box实例化对象抛发事件
b.dispatch();
//在这里e也应该为EmitterEvent类型
function eventHandler(e:EmitterEvent):void{
    console.log(e);
}
//第二个事件函数
function eventHandler1(e:EmitterEvent):void{
    console.log(e);
}

最后我们就完成了利用ts重构Event事件类;最后运行会得到事件对象
在这里插入图片描述

你可能感兴趣的:(JavaScript,TypeScript,typescript,javascript)