专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »Javascript教程 » javascript代码:javascript事件模型代码 »正文

javascript代码:javascript事件模型代码

来源: 发布时间:星期六, 2008年12月27日 浏览:28次 评论:0
本节稍稍深入地讨论有关事件处理话题如果你对模式、闭包和面向对象等概念还不太理解不妨暂且等阅读完相关内容的后再回过头来阅读它相信你会有很大收获
1 事件处理模式
设计领域“事件处理”是种模式个对象受外部影响而改变状态时通过消息方式将这个状态改变通知给这个对象或者相关联某个对象让它执行对应动作这就是事件处理基本原理负责通知状态改变对象被称作“消息”而执行响应动作属性则被称作“事件代理”
例如下面就是个简单事件处理模式应用:
function dispatchEvent(owner, eventType, eventArgs)
{
(owner && owner["on"+eventType])
Timeout(function{owner["on"+eventType](eventArgs)}, 1);
}
function randomSerials(len)
{
function randomSignal
{
Math.random > 0.5 ? 1 : 0;
}
var ret = ;
for(var i = 0; i < len; i)
{
ret.push(randomSignal);
}
ret;
}
function Dfer(obl)
{
var buffer = Array(obl);
var time = 0;
this.readBuffer = function
{
var buf = buffer;
buffer = Array(obl);
time = 0;
buf;
}
this.bufferSize = function
{
obl;
}
this.input = function(serials)
{
for(var i = 1; i < serials.length; i)
{
var signal = Math.abs(serials[i] - serials[i - 1]);
buffer[time % obl] = signal;
(signal)
dispatchEvent(this, "signalchange",
{input:serials, time:time, buffer:buffer.slice(0)});
}
}
}
var inputSerials = randomSerials(20);
alert(inputSerials);
var df10 = Dfer(20);
df10.input(inputSerials);
alert(df10.readBuffer);
df10.onsignalchange = function(eventArgs)
{
alert(eventArgs.time);
}
df10.input(inputSerials);
在上面例子中dispatchEvent负责分派事件onsignalchange是事件代理在这个差分系统df10中当输入信号电平发生变化(从0到1或者从1到0)时触发相应事件onsignalchange并且将当前输入信号、时序和当前输出缓存Cache作为事件参数传入事件处理
df10.onsignalchange = function(eventArgs)
{
alert(eventArgs.time);
}
员指定事件处理在这里我们打印出输入电平发生变化时输入信号时序
2 用户事件接口定义
前面例子中我们仅仅定义了个用来分派事件dispatchEvent但它也可以看作是个完整用户事件接口现在我们回顾这个弄明白它究竟做了什么样事情:
function dispatchEvent(owner, eventName, eventArgs)
{
(owner && owner["on"+eventName])
Timeout(function{owner["on"+eventName](eventArgs)}, 1);
}
这个接收 3个参数个参数是个对象指定了这个事件“所有者”即这个事件是由谁接收和负责处理在上面例子中这个owner是Dfer对象本身即
dispatchEvent(this, "signalchange", {input:serials, time:time, buffer:buffer});
传入owner参数是this实际上事件模式允许其他类型作为事件分派所有者尤其在些特定模式通常事件发起者和事件接收者可以不是同个对象在4小节介绍观察者模式中可以看到这
第 2个参数是个表示事件类型它决定了事件代理名称根据事件模型规范标准事件代理名称为”on”+事件类型例如上面例子中事件类型为signalchange对应事件代理为onsignalchange
第 3个参数是个事件参数对象它决定了传递给事件接收者参数在上面例子中它传递了input、time和buffer 3个属性分别代表发生事件时当前输入序列、时序以及输出缓存Cache
dispatchEvent本身内容很简单它只是确保接收者事件代理并将事件参数正确传入这个事件代理至于事件代理是如何处理事件参数它并不关心
3 事件代理和事件注册
在事件处理模式中为事件代理指定事件处理过程被称为事件注册在上面例子中df10.onsignalchange是极其简单事件代理事件注册过程也极为简单——采用直接赋值方式来完成
事实上根据设计区别事件代理可以有更加复杂注册方式例如DOM-level-2addEventListener和removeEventListener我们也可以实现类似事件注册思路方法以支持为个事件代理注册多个事件事件处理思路方法为了实现它我们完善事件接口修改上面例子如下:
function EventManager(owner)
{
owner = owner || this;
this.dispatchEvent = function(eventType, eventArgs)
{
var events = owner["on"+eventType];
(events && typeof(events) "function")
events = [events];
(owner && events)
{
for(var i = 0; i < events.length; i)
{
Timeout(
(function(i){ function{events[i](eventArgs)}
})(i), 1
);
}
}
}
this.addEventListener = function(eventType, closure)
{
(owner["on"+eventType] null)
{
owner["on"+eventType] = ;
}
var events = owner["on"+eventType];
(events && typeof(events) "function")
events = [events];
events.push(closure);
}
this.removeEventListener = function(eventType, closure)
{
var events = owner["on"+eventType];
(events && typeof(events) "function")
events = [events];
for(var i = 0; i < events.length; i)
{
(events[i] closure)
events.splice(i, 1);
}
}
}
function randomSerials(len)
{
function randomSignal
{
Math.random > 0.5 ? 1 : 0;
}
var ret = ;
for(var i = 0; i < len; i)
{
ret.push(randomSignal);
}
ret;
}
function Dfer(obl)
{
var buffer = Array(obl);
var time = 0;
EventManager.call(this); //apply EnventManager Component.
this.readBuffer = function
{
var buf = buffer;
buffer = Array(obl);
time = 0;
buf;
}
this.bufferSize = function
{
obl;
}
this.input = function(serials)
{
for(var i = 1; i < serials.length; i)
{
var signal = Math.abs(serials[i] - serials[i - 1]);
buffer[time % obl] = signal;
(signal)
this.dispatchEvent("signalchange",
{input:serials, time:time, buffer:buffer.slice(0)});
}
}
}
var inputSerials = randomSerials(20);
alert(inputSerials);
var df10 = Dfer(20);
df10.input(inputSerials);
alert(df10.readBuffer);
var eventHandler1 = function(eventArgs){
alert(eventArgs.time);
}
var eventHandler2 = function(eventArgs){
alert(eventArgs.buffer);
}
df10.addEventListener("signalchange",eventHandler1);
df10.addEventListener("signalchange",eventHandler2);
df10.input(inputSerials);
df10.removeEventListener("signalchange",eventHandler1);
在上面例子里我们建立了个EventManager类型为它定义了 3个对象思路方法dispatchEvent思路方法和前面那个例子很类似是用来分派事件而另外addEventListener和removeEventListener则是用来注册和注销事件处理
在Dfer类型中我们通过EventManager.call(this);将EventManager类型例子运用到Dfer原型中(有关这个问题深层机制留待以后再进行详细讨论)然后this.dispatchEvent来分派事件
在为Dfer例子onsignalchange事件代理注册事件时你会发现它和标准DOM事件模型非常类似:
df10.addEventListener("signalchange",eventHandler1);
df10.addEventListener("signalchange",eventHandler2);
df10.removeEventListener("signalchange",eventHandler1);
运行过这个例子你会发现个有趣地方就是df10.input(inputSerials);触发事件并没有执行eventHandler1和eventHandler2而是只执行了eventHandler2原因是:
df10.removeEventListener("signalchange",eventHandler1);
先于事件触发被执行这是事件机制是种“异步回调”机制有关同步和异步问题我们以后讨论
4 标准模式:事件分派和接收
在事件处理模式中事件分派者负责发出消息事件接收者负责处理消息在前面例子里它们是由同个对象(Dfer)完成
然而事实上事件处理模式中并不要求消息发送和接收由同个对象完成在某些模式中它们是区别对象其中最常见种是“观察者”模式下面将差分系统例子改写为观察者模式:
function dispatchEvent(owner, eventType, eventArgs)
{
(owner && owner["on"+eventType])
Timeout(function{owner["on"+eventType](eventArgs)}, 1);
}
function randomSerials(len)
{
function randomSignal
{
Math.random > 0.5 ? 1 : 0;
}
var ret = ;
for(var i = 0; i < len; i)
{
ret.push(randomSignal);
}
ret;
}
function DferObserver(dfer)
{
this.dfer = dfer;
dfer.Observer(this);
}
function Dfer(obl)
{
var buffer = Array(obl);
var time = 0;
var observer = null;
this.input = function(serials)
{
for(var i = 1; i < serials.length; i)
{
var signal = Math.abs(serials[i] - serials[i - 1]);
buffer[time % obl] = signal;
(signal)
dispatchEvent(observer, "signalchange", {sender:this, input:serials, time:time, buffer:buffer.slice(0)});
}
}
this.Observer = function(obs)
{
observer = obs;
observer.readBuffer = function
{
var buf = buffer;
buffer = Array(obl);
time = 0;
buf;
}
observer.bufferSize = function
{
obl;
}
}
}

var inputSerials = randomSerials(20);
alert(inputSerials);
var df10 = Dfer(20);
df10.input(inputSerials);
var dfObs = DferObserver(df10);
alert(dfObs.readBuffer);
dfObs.onsignalchange = function(eventArgs)
{
(df10 eventArgs.sender)
alert(eventArgs.time);
}
df10.input(inputSerials);
上面例子中事件分派者是Dfer类型而事件接收者则是DferObserver类型所以事件注册代理是DferObserver属性在发送事件参数中我们增加了个属性sender它引用事件实际发送对象
原文:http://bbs.51js.com/thread-69808-1-1.html by 月影
0

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: