javascript实现Observer模式来管理多个事件回调
《实战ajax》第四章介绍了这样的一个模型,与java中的事件处理模型相一致,观察者——监听者模式,感觉很酷:)。比如,我要对ID为mousemat的div标签的onclick事件增加两个事件writestatus()和drawThumbnail(),更新状态栏和重定位鼠标位置这两个事件,典型的代码应该像这样:
window.onload=function(){
var mat=document.getElementById('mousemat');
mat.onclick=mouseObserver;
cursor=document.getElementById('cursor');
}
function mouseObserver(event){
var e=window.event||event;
writeStatus(e)
drawThumbnail(e)
}
这样的方式目前看起来还算清晰,但是当事件增多时将不可避免地复杂起来,如果我们能像java中的事件处理模型那样直接addListener该多好,书中给出了例子:
window.onload=function(){
var mat=document.getElementById('mousemat');
cursor=document.getElementById('cursor');
var mouseRouter=new jsEvent.EventRouter(mat,"onclick");
mouseRouter.addListener(writeStatus);
mouseRouter.addListener(drawThumbnail);
}
引入了一个EventRouter对象,此对象完整代码如下:
requires extras-array.js
var jsEvent=new Array();
jsEvent.EventRouter=function(el,eventType){
this.lsnrs=new Array();
this.el=el;
el.eventRouter=this;
el[eventType]=jsEvent.EventRouter.callback;
}
jsEvent.EventRouter.prototype.addListener=function(lsnr){
this.lsnrs.append(lsnr,true);
}
jsEvent.EventRouter.prototype.removeListener=function(lsnr){
this.lsnrs.remove(lsnr);
}
jsEvent.EventRouter.prototype.notify=function(e){
var lsnrs=this.lsnrs;
for(var i=0;i<lsnrs.length;i++){
var lsnr=lsnrs[i];
lsnr.call(this,e);
}
}
jsEvent.EventRouter.callback=function(event){
var e=event || window.event;
var router=this.eventRouter;
router.notify(e)
}
这段代码并不难理解,实现了一个事件顺序数组,增加的监听器函数通过Function.call()调用。两个方法addListener和removeListener真正实现了清晰的事件模型。