上一篇给foo类增加了
addEvent和removeEvent方便事件的注册与注销
这次总结下自定义事件的几种方法
程序代码
<script type="text/javascript">
<!--
var foo = function(){ this.init.apply(this,arguments);};
foo.prototype = {
init:function(_name){
this.name = _name;
this.addEvent('click',document,this.say,this,'hello world!');
},
say:function(_ev,_word){
alert(this.name +':' +_word);
this.stop();
this.onSay(_word);
},
stop:function(){
this.removeEvent('click',document,this.say);
},
addEvent:function(_event,_element,_fn,_scope,_args){
var args = Array.prototype.slice.call(arguments, 0);
ev = args.shift(),
element = args.shift(),
fn = args.shift(),
scope = args.length>0?args.shift():window;
element['e'+ev+fn] = function(_ev){
_ev == _ev || window.event;
args.unshift(_ev);
fn.apply(scope,args);
};
if (element.addEventListener) {
element.addEventListener(ev, element['e'+ev+fn], false);
} else if (element.attachEvent) {
element.attachEvent("on" +ev, element['e'+ev+fn]);
}
},
removeEvent:function(_event,_element,_fn){
if (_element.removeEventListener) {
_element.removeEventListener(_event, _element['e'+_event+_fn], false);
} else if (_element.detachEvent) {
_element.detachEvent("on" +_event, _element['e'+_event+_fn]);
}
try {
delete _element['e'+_event+_fn];
}catch(_ex){
_element['e'+_event+_fn] = null;
}
},
onSay:function(){}
}
var a = new foo('llinzzi');
a.onSay = function(_word){
alert('事件:'+this.name +'刚说了'+ _word);
}
增加了个onSay的事件,在类定义的时候只定义成空函数,然后在需要的时候调用,定义具体的方法是在类实例化后,给实例中的onSay
缺点是只能定义一次的onSay的回调,如果多次定义后面的会把前面的覆盖掉,修改一下。
程序代码
var foo = function(){ this.init.apply(this,arguments);};
foo.prototype = {
init:function(_name){
this.name = _name;
this.addEvent('click',document,this.say,this,'hello world!');
},
say:function(_ev,_word){
alert(this.name +':' +_word);
this.stop();
this._onSay(_word);
},
stop:function(){
this.removeEvent('click',document,this.say);
},
addEvent:function(_event,_element,_fn,_scope,_args){
var args = Array.prototype.slice.call(arguments, 0);
ev = args.shift(),
element = args.shift(),
fn = args.shift(),
scope = args.length>0?args.shift():window;
element['e'+ev+fn] = function(_ev){
_ev == _ev || window.event;
args.unshift(_ev);
fn.apply(scope,args);
};
if (element.addEventListener) {
element.addEventListener(ev, element['e'+ev+fn], false);
} else if (element.attachEvent) {
element.attachEvent("on" +ev, element['e'+ev+fn]);
}
},
removeEvent:function(_event,_element,_fn){
if (_element.removeEventListener) {
_element.removeEventListener(_event, _element['e'+_event+_fn], false);
} else if (_element.detachEvent) {
_element.detachEvent("on" +_event, _element['e'+_event+_fn]);
}
try {
delete _element['e'+_event+_fn];
}catch(_ex){
_element['e'+_event+_fn] = null;
}
},
_onSay:function(){
if(!this._onSayArray) return;
for(var i=0; i<this._onSayArray.length; i++){
this._onSayArray[i].apply(this,arguments);
}
},
addOnSay:function(_fn){
if(!this._onSayArray) this._onSayArray = new Array();
this._onSayArray.push(_fn);
}
}
var a = new foo('llinzzi');
a.addOnSay(function(_word){
alert('事件1:'+this.name +'刚说了'+ _word);
});
a.addOnSay(function(_word){
alert('事件2:'+this.name +'刚说了'+ _word);
});
实例通过addOnSay方法来增加事件响应,可以增加多个。
缺点,代码繁琐,如果要增加addOnSayAfter addOnSayBefore 就要增加很多代码。
再修改一下
程序代码
var foo = function(){ this.init.apply(this,arguments);};
foo.prototype = {
init:function(_name){
this.name = _name;
this.addEvent('click',document,this.say,this,'hello world!');
},
say:function(_ev,_word){
this.fireEvent('saybefore',_word);
alert(this.name +':' +_word);
this.stop();
this.fireEvent('sayafter',_word);
},
stop:function(){
this.removeEvent('click',document,this.say);
},
addEvent:function(_event,_element,_fn,_scope,_args){
var args = Array.prototype.slice.call(arguments, 0);
ev = args.shift(),
element = args.shift(),
fn = args.shift(),
scope = args.length>0?args.shift():window;
element['e'+ev+fn] = function(_ev){
_ev == _ev || window.event;
args.unshift(_ev);
fn.apply(scope,args);
};
if (element.addEventListener) {
element.addEventListener(ev, element['e'+ev+fn], false);
} else if (element.attachEvent) {
element.attachEvent("on" +ev, element['e'+ev+fn]);
}
},
removeEvent:function(_event,_element,_fn){
if (_element.removeEventListener) {
_element.removeEventListener(_event, _element['e'+_event+_fn], false);
} else if (_element.detachEvent) {
_element.detachEvent("on" +_event, _element['e'+_event+_fn]);
}
try {
delete _element['e'+_event+_fn];
}catch(_ex){
_element['e'+_event+_fn] = null;
}
},
fireEvent:function(){
var args = Array.prototype.slice.call(arguments, 0);
var _event = args.shift();
if(!this.cusEvents) return;
if(!this.cusEvents[_event]) return;
for(var i=0; i<this.cusEvents[_event].length; i++){
this.cusEvents[_event][i].apply(this,args);
}
},
catchEvent:function(_event,_fn){
if(!this.cusEvents) this.cusEvents = {}
if(!this.cusEvents[_event]) this.cusEvents[_event] = new Array();
this.cusEvents[_event].push(_fn);
}
}
var a = new foo('llinzzi');
a.catchEvent('saybefore',function(_word){
alert('事件1:'+this.name +'想说'+ _word);
});
a.catchEvent('sayafter',function(_word){
alert('事件2:'+this.name +'刚说了'+ _word);
});
最后如果将catchEvent fireEvent addEvent removeEvent 单独放在一个类.EventHeloper
将addEvent和catchEvent整合
EventHeloper.addEvent(element/object,dom event/custom event,callback) 这样还是很方便的。
程序代码
EventHelper = {
Events:{Dom:{},Custom:{}},
addEvent:function(_object,_event,_fn,_scope,_args){
var args = Array.prototype.slice.call(arguments, 0),
obj = args.shift(),
ev = args.shift(),
fn = args.shift(),
scope = args.length>0?args.shift():window;
var eType = obj.nodeType?'Dom':'Custom';
var fun;
if(eType=='Dom'){
sfn = function(_ev){
_ev == _ev || window.event;
args.unshift(_ev);
fn.apply(scope,args);
}
if (obj.addEventListener) {
obj.addEventListener(ev,sfn, false);
} else if (obj.attachEvent) {
obj.attachEvent("on" +ev,sfn);
}
}else {
sfn = function(){
var __sargs = Array.prototype.slice.call(arguments, 0);
var _sargs = __sargs.concat(args);
fn.apply(scope,_sargs);
}
}
fun = { fn:fn,sfn:sfn };
this.Events[eType][obj] = this.Events[eType][obj] || {};
this.Events[eType][obj][ev] = this.Events[eType][obj][ev] || new Array();
this.Events[eType][obj][ev].push(fun);
},
removeEvent:function(_object,_event,_fn){
var obj = _object,
ev = _event,
fn = _fn;
var eType = obj.nodeType?'Dom':'Custom';
if(!this.Events[eType][obj]) return;
var fun;
for( var i=0; i<this.Events[eType][obj][ev].length;i++){
if(fn == this.Events[eType][obj][ev][i].fn){
fun = this.Events[eType][obj][ev][i].sfn;
this.Events[eType][obj][ev].splice(i,1);
break;
}
}
if(eType=='Dom'){
if (obj.removeEventListener) {
obj.removeEventListener(ev, fun, false);
} else if (obj.detachEvent) {
obj.detachEvent("on" + ev, fun);
}
}
},
fireEvent:function(_object,_event){
var args = Array.prototype.slice.call(arguments, 0),
obj = args.shift(),
ev = args.shift();
var eType = 'Custom';
if((!this.Events[eType][obj]) || (!this.Events[eType][obj][ev])) return;
for(var i=0; i<this.Events[eType][obj][ev].length; i++){
this.Events[eType][obj][ev][i].sfn.apply(window,args);
}
}
}
修改一下演示的例子
上面例子的 EventHelper.addEvent方法可以增加自定义事件或者原生的事件
EventHelper.addEvent(document,'click',function(){alert('hello');}); // 原生事件
EventHelper.addEvent(foo,'say',function(){alert('hello');}); // 自定义时间
对应的EventHelper.removeEvent也可以移除自定义事件。