现在的位置: 首页 > 综合 > 正文

自定事件

2018年01月28日 ⁄ 综合 ⁄ 共 2232字 ⁄ 字号 评论关闭

GOF对观察者模式的定义:Observer的意图是定义对象之间的一种一(被观察者)对多(观察者)的关系,当一个对象的状态发生改变时,所有依赖它的对象得到通知,并且会自动更新自己。

从这段经典的定义中,可以推测下,观察者模式中的俩个对象各自应该拥有的特征
1,被观察者应该可以注册观察者,注销观察者。
2,持有对其注册的观察者。
3,当自身改变时,依赖于特性一,其可以通知对其注册的观察者。
4,观察者会自动更新自己。
5,被观察者应该是独立的,也就是说,观察者影响其并不会影响被观察者。

java与js的事件机制都可以说观察者模式的应用场景。
在java的世界中借助于
java.util.Observable
java.util.Observer

中这俩个类可以非常简便的实现观察者模式-(java的awt的事件机制在底层就是借助观察者模式实现的,这也可以算是搭建java世界中事件机制的支撑基础类了)

对于js的事件,譬如,在一个DOM元素(被观察者)上的单击事件,观察者(也就是在这个事件上的回调函数)会关注这个很特别的时刻,并且做出反应。


在写js的自定义事件之前,先看一下曾经令我十分好奇的EXT的自定义事件
部分代码来自 《深入浅出EXTJS》和《javascript高级程序设计》(第二版)
Person=function(name){
    this.name=name;
    this.addEvents('work','read');
};
Ext.extends(Person,Ext.util.Observable);

当自定义的类继承了Ext.util.Observable后,自定义的类便可以支持事件。

var sz=new Person('sz');
sz.on('work',function(){//为Person的实例绑定监听,即把观察者注册到要被观察者
    Ext.Msg.alert('宋峥,在工作那!');
});

下面,来触发这个事件,其实原理很简单,就是让'work'事件对应处理函数执行。
sz.fireEvent('work');//回调函数执行

很神奇,其实这就是封装的力量,EXT对原生js的封装,让实现自定义事件变的如此简单。
来看看《javascript高级程序设计》(第二版)对是自定义事件的实现(有小改动)。
对EXT自定义的事件的实现的原理?是不是已经相当透彻了?是不是可以联系到观察者设计模式?
   
    function Obserable(){
        this.handlers={};//持有事件处理函数
    }
    Obserable.prototype={//重写EventTarget的原型对象
        constructor:EventTarget,
        on:function(type,handler){//对应于观察者模式-在相应的被观察者注册观察者
            //handlers中是否已有针对此事件类型的数组
            //没有创建一个空数组
            //把这个处理函数推入对应的handlers[type]数组,
            if(typeof this.handlers[type]=="undefined"){
                this.handlers[type]=[];
            }
            this.handlers[type].push(handler);
        },
        fireEvent: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;len=handlers.length;i++){
                    handlers[i]();//回调函数执行,也就是观察者更新自己
                }
            }
        }
    };
    
    function handlerMessage(event){
        alert("处理函数被回调");
    }
    var ob=new Obserable();
    ob.on('message',handlerMessage);
    ob.fireEvent({type:'message'});

至此,只要继承了此Obserable类的相应类的实例都可以成为被观察者了,也就都可以支持事件了,这也就和EXT的自定义事件的思路没多大差异了,当然EXT的设计更加巧妙。越来越有看EXT源码的欲望了,但水平还不够,还需努力。

最后,不难发现,原生态的事件,是在某一个特殊时刻(单击,获得焦点等等)发生时,由游览器把这一特殊时刻的一些信息,譬如事件类型,和其他的一些必要信息封装成event对象,触发事件处理程序时把这个event对象作为实参传入,而我们自定义的事件,当然只能由我们自己触发,传入的实参event也是我们自己传入的(这个event,想封装什么就封装什么,需要什么就封装什么).

抱歉!评论已关闭.