庄周梦蝶

生活、程序、未来
   :: 首页 ::  ::  :: 聚合  :: 管理

传统javascript事件模型实现观察者模式

Posted on 2007-03-16 09:19 dennis 阅读(1891) 评论(0)  编辑  收藏 所属分类: web开发
    在W3C新的事件模型框架中,IE和Mozilla都实现了相应的版本,IE的是attachEvent和detachEvent来实现元素事件的添加和删除,而Mozilla则是标准的addEventListener和 removeEventListener。在传统的javascript事件模型中,我们没办法为一个页面元素注册多个事件,只有靠自己来实现观察者模式。代码来自《ajax in action》,我添加了注释
//命名空间
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);
 }
};
//回调函数调用notify
jsEvent.EventRouter.callback=function(event){
 
var e = event || window.event;
 
var router = this.eventRouter;
 router.notify(e);
};

Array.prototype.append 
= function(obj,nodup){
 
if(nodup){ 
  
this[this.length]=obj;
 }
};
Array.prototype.remove 
= function(o)
{
   
var i = this.indexOf(o);
   
if (i>-1)
  {
    
this.splice(i,1);
   }
     
return (i>-1);
   }  
}; 

这里比较巧妙的就是
 el.eventRouter = this;
//注册回调函数
 el[eventType] = jsEvent.EventRouter.callback;

首先给el元素添加属性
eventRouter是当前的EventRouter对象,然后,比如eventType假设为onclick,el是一个button元素,那么这里就是el[onclick]=jsEvent.EventRouter.callback;相当于el.onclick=jsEvent.EventRouter.callback;
而请注意这个回调函数
callback将首先得到元素的eventRouter对象,再调用此对象的notify方法触发所有注册的事件。

再请注意notify函数里面这一行:
 lsnr.call(this,e);

我们把event对象传入此函数作参,而
var e = event || window.event;那么所有事件函数的第一个参数都将是event对象,避免了IE需要通过window.event得到的事件对象的浏览器不一致行为。

使用此对象方式:
 var mat=document.getElementById('mousemat');
  cursor
=document.getElementById('cursor');
  
var mouseRouter=new jsEvent.EventRouter(mat,"onmousemove");
  mouseRouter.addListener(writeStatus);
  mouseRouter.addListener(drawThumbnail); 



只有注册用户登录后才能发表评论。


网站导航: