但目前发现唯一不足的就是,js的自定义事件,目前还不被大部分浏览器支持,这给开发带来了一些不便。虽然js内部定义的事件丰富,但是也仅限于UI事件,BOM事件和DOM事件,对于某些领域(比如自己开发的控件,游戏等需要自己在某些时候调用特定方法,或者是习惯于观察者模式的开发者)来说,这也是一种缺陷吧。
为此,鄙人写了个js类来模拟javascript中的事件,代码如下:
BaseEvent.js
function BaseEvent(type,data){
var This = this;
This.type = type;//String
This.data = data;//Object
function Constructor(){
}
Constructor();
}
这里定义一个类型和一个数据,数据用来传递参数。这里没有用到js原生的事件原理(捕获,目标,冒泡),是因为我们自己定义的事件,都是我们自己触发的,不需要这样的机制。这个类算是一个基类,可以拓展成各种子类,以及模块类(到时候写完会分享出来)。
EventDispatcher.js
function EventDispatcher(){
var This = this;
/**
* type String
* data [handlers]
*/
This.registeredData = {};
EventDispatcher.prototype.addCustomEventHandler = function(type,handler){
if((typeof type != "string")){
throw new Error("error event!!!");
}
if(!(typeof handler == "function")){
throw new Error("error method!!!");
}
if (This.registeredData[type] == null) {
This.registeredData[type] = new Array();
}
try {
if (This.registeredData[type].indexOf(handler) == -1) {
This.registeredData[type].push(handler);
}
} catch (e) {//IE8及以下的版本不支持indexOf方法
var len = This.registeredData[type].length;
if(len == 0){
This.registeredData[type].push(handler);
}
for (var i=0; i<len; i++) {
if(This.registeredData[type][i] === handler){
This.registeredData[type].push(handler);
break;
}
};
}
};
EventDispatcher.prototype.removeCustomEventHandler = function(type,handler){
if((typeof type != "string")){
throw new Error("error event!!!");
}
if(!(typeof handler == "function")){
throw new Error("error method!!!");
}
var handlers = This.registeredData[type];
var index;
try {
if((index = handlers.indexOf(handler)) != -1){
handlers.splice(index,1);
}
} catch (e) {//IE8及以下的版本不支持indexOf方法
for (var i=0,len = handlers.length; i<len; i++) {
if(handlers[i] === handler){
handlers.splice(i,1);
}
};
}
if(This.registeredData[type].length == 0)This.registeredData[type] = null;
};
EventDispatcher.prototype.dispatchCustomEvent = function(evt){
if(!(evt instanceof BaseEvent)){
throw new Error("error event!!!");
}
if(This.registeredData[evt.type] != null){
for (var i=0,len = This.registeredData[evt.type].length; i<len; i++) {
This.registeredData[evt.type][i](evt);
};
}
};
EventDispatcher.prototype.dispose = function(){
for(var arr in registeredData) {
while(arr.length != 0){
arr.shift();
}
};
registeredData = null;
};
}
这个类是事件注册/取消注册/监听的核心类,主要由3个方法组成:
一、addCustomEventHandler(type,handler)方法:
注册监听事件
type:String 事件类型
handler:function 处理方法
这和js原生的增加事件监听差不多,只不过,handler在回调的时候,传的是我们自己定义的事件对象,这有一个好处,js原生的事件对象的继承各种浏览器支持不一,用自己的对象可以自由增加删除属性和方法。
二、removeCustomEventHandler(type,handler)方法:
取消注册事件监听
这个方法和addCustomEventHandler类似,就是取消对某个事件的监听,也是和js原生的相似。需要注意的是,这里的handler和addCustomEventHandler的handler必须是同一个对象的引用,才能移除监听。
三、dispatchCustomEvent(evt)方法
这个方法就是触发一个事件(自己定义的BaseEvent或子类)
这个方法就是我写这个东东的原因了,在js中,可以触发内部事件,但是,这样就给开发带来了一些不便,在游戏中,很多模块加载完,都是需要事件的,人物移动完成,技能释放完成,等等,都是需要事件的(这里讲得偏游戏了,不过不仅仅游戏,很多也是同样的道理)。用这个方法,就能很好的派发出自己的事件,让“观察者”来处理各自的需求了。这个方法也是模仿自AS3.0的事件机制。
四、dispose()方法
释放资源(游戏中这极其重要,别的领域应该也是吧)
用法:
首先,需要一个事件分发器dispatcher
var distpatcher = new EventDispatcher();
var fun = function(e){
alert(e.data);
//distpatcher.removeCustomEventHandler("cck",arguments.callee);//移除监听
};
distpatcher.addCustomEventHandler("cck",fun);
这里,就是注册监听,由于js实现接口比较麻烦,所以,dispatcher通常用作组合,作为对象的成员,这样,每个类都有自己的分发器,处理各自的事件请求。
然后,在需求触发事件的时候,调用如下代码:
distpatcher.dispatchCustomEvent(new BaseEvent("cck","i love you"));
这里,dispatcher派发了一个事件BaseEvent对象,type为"cck",data为"i love you"的String对象,在以上的监听中,就会弹出“i love you”警告框。
主要工作原理就差不多如上。
这可能有待改进,我也会再看看项目的代码和看看js的理论,多写一些方便大家使用的东西来共享,谢谢。
--------------------------------------------