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

来看一下这个东西mousemat.html:

<html> 
<head>
<link rel='stylesheet' type='text/css' href='mousemat.css' />
<script type='text/javascript'>

var cursor=null

window.onload=function(){
var mat=document.getElementById('mousemat');
mat.onmousemove=mouseObserver;
cursor=document.getElementById('cursor');
}

function mouseObserver(event){
var e=event || window.event;
writeStatus(e)
drawThumbnail(e)
}

function writeStatus(e){
window.status=e.clientX+","+e.clientY
}

function drawThumbnail(e){
cursor.style.left=((e.clientX/5)-2)+"px";
cursor.style.top=((e.clientY/5)-2)+"px";
}
</script>
</head>

<body>
<div class='mousemat' id='mousemat'></div>
<div class='thumbnail' id='thumbnail'>
<div class='cursor' id='cursor'></div>
</div>
</body>
</html>

并附上还有要用到的mousemat.css
.body{
background-color: white;
}
.mousemat{
background-color: #ffe0d0;
border: solid maroon 2px;
width: 500px;
height: 500px;
top: 24px;
left: 24px;
position: absolute;
}
.thumbnail{
background-color: cyan;
border: solid navy 1px;
width: 100px;
height: 100px;
top: 24px;
left: 528px;
position: absolute;
margin:0px;
padding: 0px;
}
.cursor{
background-color: navy;
width:3px;
height: 3px;
position: relative;
}


试试看,什么效果,然后再继续下面的吧


下面的会是同样的效果,只是代码复杂了,当然下面的代码是不完整的,只是核心部分。

首先简单介绍下需要模拟的东西,在W3C新的事件模型框架中,IE和Mozilla都实现了相应的版本,在基于Mozilla的浏览器和Safari中,使用addEventListener()来附加时间按回调,使用相应的removeEventListener()来删除,IE提供了类似的函数:attachEvent()和detachEvetn()。在传统的javascript时间模型中,我们无法为一个元素注册多个事件(任何事件),如何解决?
恩,是的,只有靠自己来实现观察者模式了。下面的代码来自《ajax in action》,加入了注释及相关说明。
注:对于观察者模式(Observer)是设计模式的一种,可以查看资料。


//命名空间,是的,只是一种形式
var jsEvent = new Array();

//构造函数
//其中的el在实际中表示的是页面的dom元素(可以是一个button元素,一个div元素等等等),eventType表示的是事件对象(如onclick等等等)
jsEvent.EventRouter = function(el,eventType){

//内部维护一个事件列表,这里的lsnrs很重要,里面存放当事件发生时我们需要的执行事件,是一个数组,所以允许我们把很多事件放进去
this.lsnrs = new Array();
this.el = el;
el.eventRouter = this; //给el元素(记住el是一个页面元素)添加属性eventRouter,这个属性是当前的EventRouter对象

//注册回调函数,恩,已经知道了前面的,现在可以翻译下下面这一句了
//类似于:el.onclick = jsEvent.EventRouter.callback;(后面只是一个当onclick事件发生时需要执行的事件函数而已,具体的callback是什么将在后面的代码中涉及)
el[eventType] = jsEvent.EventRouter.callback;
};

//添加事件,使用了原型,注意添加在了哪里,是的,在上面那个构造函数里,什么用呢?答案是将需要在eventType(如onclick事件)发生时执行的动作事件放到lsnrs数组中,这里只是放进去,并没有执行。对于里面的执行的函数,下面也会说明,现在只是理清过程
jsEvent.EventRouter.prototype.addListener = function(lsnr){
this.lsnrs.append(lsnr,true);
} ;

//移除事件,类似上面的增加事件
jsEvent.EventRouter.prototype.removeListener = function(lsnr){
this.lsnrs.remove(lsnr);
};

//通知所有事件,仍然看清楚这个属性函数加在了哪里,是的,还是在构造函数内,这个notify属性是真正执行、当事件发生时(如el元素被onclick)、需要执行的、被上面函数加在lsnrs数组中的、事件。这里用了奇怪的标点,只是为了不要产生误解
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,看到了么,callback属性出现了,每当事件发生,都将调用notify函数,这样需要被执行的时间将被不断执行
jsEvent.EventRouter.callback=function(event){
var e = event || window.event;
var router = this.eventRouter;
router.notify(e);
};


//下面的函数是用在addListener和removeListener中的,意思大家应该猜得出来了

//直接在内建类array中增加原型,所有array类的对象都可以使用,其中obj是事件,当事件发生时需要执行的事件,obj对象需要有一个实现,而这里没有,nodup函数只是用来判断,当true时有效
Array.prototype.append = function(obj,nodup){
if(nodup){
this[this.length]=obj; //为什么位置在this.length?恩,这里不明说了,自己动脑筋吧
}
};

//o表示当lsnrs数组中的一个元素,代表一个事件
Array.prototype.remove = function(o)
{
var i = this.indexOf(o);
if (i>-1)
{
this.splice(i,1); //这个函数的作用是:The splice() method is used to remove and add new elements to an array。splice(数组起始位置,删除元素个数,添加的新元素【0】,……,添加的新元素【n】),是的大概是这样的,这里的表示现在该清楚了吧

}
return (i>-1);
}
};

好了,如何使用上面的对象呢:
var mat=document.getElementById('mousemat');
cursor=document.getElementById('cursor');

var mouseRouter=new jsEvent.EventRouter(mat,"onmousemove");
mouseRouter.addListener(writeStatus); //这里面的事件嘛就需要自己写了
mouseRouter.addListener(drawThumbnail); //这里也一样


当然这里的只是些核心代码,如果需要运行,当然还要增加一些必要的东西。那么就到此为止吧,codd和他的朋友们头痛了~~~~~~
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值