在JS中,面向对象架构的事件框架

分享于 

8分钟阅读

Web开发

  繁體 雙語

介绍

本文将介绍我开发的事件框架。 它让我有一个更传统的面向对象的开发JavaScript方法。

背景

在 HTML 4中作为客户端编辑器,我需要一种简单的方法来创建与它的他语言相同的事件。

JavaScript中的方法调用

很多语言都有反射库,因此你可以最好地利用面向对象语言的多态性。 JavaScript没有反射库,但你可以调用一个方法,同时控制运行它的上下文。

过程使用函数的" call"方法进行工作。 下面的示例演示了" call"方法的简单实现:

var fTest = function() { alert('test'); }
fTest.call();

这将调用 fTest 方法并显示警告框。

你还可以在通过" call"调用该方法时提供上下文。 根据上下文,我将引用对象引用作为" 这个 在方法正文中,请考虑以下示例:

var fTest = function(text) { alert(this.Name + ': ' + text); }var context = { Name: 'dave' };
fTest.call(context, 'forename');

生成的警报将显示'戴夫: forename。因为 context JSON对象被引用为 这个 对于方法调用, this.Name 返回'dave'。随后的参数传递到" call"方法并作为正常参数传递。

代码

第一部分代码通过使用 AddRemoveAtIndexOf 方法扩展 Array 中的对象来改进它。

在事件框架中,array 对象用于存储已经注册操作的列表。

Array.prototype.Add = function(obj) { this[this.length] = obj; }
Array.prototype.RemoveAt = function(index) {
 var result = new Array();
 var offset = 0;
 for (var x = 0; x <this.length; x++) {
 if (x!= index)
 result[result.length] = this[x];
 }
 return result;
}
Array.prototype.IndexOf = function(value) { 
 for (var x = 0; x <this.length; x++) 
 if (this[x] == value) 
 return x; 
 return -1; 
}

下一节定义 uiEvent 对象。 这是实例化以创建新事件的对象。 本文档后面将提供一个实现示例。

var uiEventRegistration = function() {
 this.ID = null;
 this.Method = null;
 this.Caller = null;
}var uiEvent = function() {
 this.TimerEvent = false;
 this.__registered = new Array();
 this.__currentID = 0;
 this.Register = function(func, caller) {
 var reg = new uiEventRegistration();
 reg.ID = this.__currentID;
 reg.Method = func;
 reg.Caller = caller;
 this.__registered.Add(reg);
 var returnID = this.__currentID;
 this.__currentID++;
 return returnID;
 }
 this.Deregister = function(RegistrationID) {
 var index = -1;
 for (var x = 0; x <this.__registered.length; x++)
 if (this.__registered[x].ID == RegistrationID) {
 index = x;
 break;
 }
 if (index!= -1) {
 this.__registered = this.__registered.RemoveAt(index);
 }
 }
 this.Fire = function() {
 if (!this.TimerEvent)
 uiTimerExecute();
 var a = arguments;
 for (var x = 0; x <this.__registered.length; x++) {
 this.__registered[x].Method.call(this.__registered[x].Caller,
 a[0] == null? null : a[0],
 a[1] == null? null : a[1],
 a[2] == null? null : a[2],
 a[3] == null? null : a[3],
 a[4] == null? null : a[4],
 a[5] == null? null : a[5],
 a[6] == null? null : a[6],
 a[7] == null? null : a[7],
 a[8] == null? null : a[8],
 a[9] == null? null : a[9])
 }
 }
}

我们现在有一个名为 uiEvent的类,它可以用来在JavaScript中创建传统事件。 下面的示例是框架的基本实现。

var eventTest = new uiEvent();var context1 = { Name: 'Dave' };var context2 = { Name: 'Chris' };function delegate1(mood) {
 alert(this.Name + ' is ' + mood);
}function delegate2(mood) {
 alert(mood + ' is not a good thing for ' + this.Name);
}
eventTest.Register(delegate1, context1);
eventTest.Register(delegate2, context2);
eventTest.Fire('sad');

在 上面 示例中,将出现两个警报。 第一个会说'dave is'。 第二个意思是'sad对chris来说不是件好事'。

不公平优先级

在 IE UI事件中,诸如 onmousemoveonkeypress 这样的事件比从 setTimeout 或者 setInterval 执行的调用。 这在开发动画框架( 该框架将在后面的文章中进一步讨论) 时产生了一个问题。

在构建拖放编辑器时,有一个重代码库链接到 onmousemove 事件。 这并不总是在下一个 onmousemove 事件注册到JavaScript引擎之前完成。 这样做的效果是阻止 setInterval 调用,直到鼠标仍然保持静止。

为了反转优先级并强制基于计时器的事件首先激发,我在事件框架中包含了以下类:

var uiTimers = new Array();var uiTimerCount = 0;function uiTimerExecute(timerID) {
 for(var x = 0; x <uiTimers.length; x++)
 {
 if (timerID == null || uiTimers[x].TimerID == timerID) {
 if (uiTimers[x].Expired()) {
 uiTimers[x].OnTick.Fire();
 var d = new Date();
 uiTimers[x].NextTime = new Date(d.getYear(), d.getMonth(), d.getDate(), 
 d.getHours(), d.getMinutes(), d.getSeconds(), 
 d.getMilliseconds() + (uiTimers[x].Interval));
 }
 }
 }
}var uiTimer = function(interval) {
 uiTimers.Add(this);
 this.Interval = interval;
 this.StartDate = new Date();
 this.NextTime = new Date(this.StartDate.getYear(), this.StartDate.getMonth(), 
 this.StartDate.getDate(), this.StartDate.getHours(), 
 this.StartDate.getMinutes(), this.StartDate.getSeconds(), 
 this.StartDate.getMilliseconds() + (interval));
 this.OnTick = new uiEvent();
 this.OnTick.TimerEvent = true;
 this.Expired = function() { returnthis.NextTime <new Date(); };
 this.TimerID = uiTimerCount;
 setInterval('uiTimerExecute(' + this.TimerID + ');', interval);
}

如果计划间隔已经过期,uiTimer 类将跟踪,并引发一个高于正常的事件,因为事件框架检查它是否过期,而不是等待 setInterval 评估运行。

下面是 uiTimer的实现示例:

var secondTicks = 0;function secondIncrement() {
 secondTicks++;
 window.status = secondTicks;
}var secondTimer = new uiTimer(1000);
secondTimer.OnTick.Register(secondIncrement);

  framework  EVE  event  arc  架构  
相关文章