介绍自定义事件之前,首先要介绍一种设计模式--观察者模式。

  • 事件是一种叫做观察者的设计模式,是一种创建松散耦合代码的技术。
  • 观察者模式有两类对象组成:主体观察者主体负责发布事件,来表示该对象声明周期某些有趣的时刻到了;观察者通过监听这些事件来观察该主体,等待某些有趣的时刻到来,并运行代码来响应。
  • 该模式的一个关键概念是主体并不知道观察者的任何事情,也就是说他可以独立存在并正常运转,即时观察者不存在。
举个例子,政府发布某个文件,下面部门根据文件执行相应的任务。政府为主体,执行人为观察者。但是政府并不知道具体执行这件事的人是谁,甚至都不知道是不是有人在执行,就好像政府让下面的人对老城区拆迁改造但是并不知道他们会强拆一样,但这并不影响政府发布文件。

涉及到DOM上,DOM元素便是主体,你的事件处理程序(即回调函数)便是观察者。

自定义事件背后的概念是创建一个管理事件的对象,让其他对象监听这些事件。具体步骤如下:

  1. 定义事件管理对象的构造函数--EventTarget,EventTarget类型有一个属性和三个方法:

    • 属性--handlers:用于存储事件处理程序
    • 方法1--addHandler():用于对给定事件类型注册事件处理程序
    • 方法2--fire(): 用于触发给定事件
    • 方法3--removeEvent():用于注销给定事件类型的事件处理程序
  2. 创建一个EventTarget类型的事件管理对象
  3. 通过addHandler()添加一个事件管理程序
  4. 通过fire()激发该事件
  5. 通过removeEvent()注销该事件

代码如下:

//定义事件管理对象的构造函数--`EventTarget`
function EventTarget(){
    this.handlers = {};
}
EventTarget.prototype = {
    constructor:EventTarget,
    
    /*
    用于对给定事件类型注册事件处理程序
    param:事件类型--type;用于处理该事件的函数--handler
    
    */
    addHandler:function(type,handler){
        if(typeof this.handlers[type] == "undefined"){//若不存在针对该事件的数组,则创建一个新数组
            this.handlers[type] = [];
        }
        this.handlers[type].push(handler);//将处理程序添加到数组中,同一事件可以有多个事件处理程序
    },
    
    /*
    用于触发给定事件
    param:{} 至少包含type属性
    
    */
    fire:function(event){
        if(!event.target){
            event.target = this;
        }
        if(this.handlers[event.type] instanceof Array){
            var handlers = this.handlers[event.type];
            for(var i = 0; i < handlers.length; i++){
                handlers[i](event);
            }
        }
    },
    
    /*
    用于注销给定事件类型的事件处理程序
    param:事件类型--type;用于处理该事件的函数--handler
    
    */
    removeHandler:function(type,handler){
        if(this.handlers[type] instanceof Array){
            var handlers = this.handlers[type];
            for(var i = 0; i < handlers.length; i++){
                if(handlers[i] === handler){
                    break;
                }
            }
            handlers.splice(i,1);
        }
    }  
};
function handleMessage(event){
    alert("Message received:" + event.message);
}
//创建事件管理对象
var target = new EventTarget();
//添加事件执行程序
target.addHandler("message",handleMessage);
//触发message事件
target.fire({type:"message",message:"Hello World"});//Message received:Hello World
//注销事件执行程序
target.removeHandler("message",handleMessage);
//再次触发message事件
target.fire({type:"message",message:"Hello World"});//无警告框

思考:

宁向东老师在得到专栏说过:相比于认知能力,拥有知识的数量的多少,并不重要,真正重要的是在学习一门知识的同时,要格外的在意这些知识所传达出来的认知逻辑。

问:自定义事件的认知逻辑是什么?
答:咳咳...应该是观察者模式吧,能力有限,具体的描述以后补上。

若理解有误,敬请斧正
详情请见js高程第22章--高级技巧


PluckyChuang
3 声望1 粉丝

正在啃js高程的前端小白


« 上一篇
Extjs 笔记