本文我们将继续讲解事件模块的演变,在上一篇解析Javascript事件模块的演变(2) 中的add有个问题,对同一类型事件添加多个hanlder时,IE6/7/8下会无序,如
01 <div id="d1" style="width:200px;height:200px;background:gold;"></div>
02 <script type="text/javascript">
03 var el = document.getElementById('d1');
04 function handler1(){alert('1');}
05 function handler2(){alert('2');}
06 function handler3(){alert('3');}
07 function handler4(){alert('4');}
08 function handler5(){alert('5');}
09 E.add(el, 'click', handler1);
10 E.add(el, 'click', handler2);
11 E.add(el, 'click', handler3);
12 E.add(el, 'click', handler4);
13 E.add(el, 'click', handler5);
14 </script>
IE9/Firefox/Safari/Chomre/Opera会依次输出1,2,3,4,5。但IE6/7/8中则不一定。为解决所有浏览器中多个事件handler有序执行,我们需要一个队列来管理所有的handler。
这次,把所有的内部细节封装在一个匿名函数中,该函数执行完毕后返回如上一篇接口相同的方法。另外
1,把真正的事件handler挂在el上,即el.listeners,其为一个对象,每一个类型的事件为一个数组,如click为el.listeners["click"] = []。
2,所有的handler存在在对于的数组中
3,删除一个hanlder,将从数组中将其删除
01 E = function(){
02 function _isEmptyObj(obj){
03 for(var a in obj){
04 return false;
05 }
06 return true;
07 }
08 function _each(ary, callback){
09 for(var i=0,len=ary.length; i<len;){
10 callback(i, ary[i]) ? i=0 : i++;
11 }
12 }
13 function _remove(el, type){
14 var handler = el.listeners[type]['_handler_'];
15 el.removeEventListener ?
16 el.removeEventListener(type, handler, false) :
17 el.detachEvent('on'+type, handler);
18 delete el.listeners[type];
19 if(_isEmptyObj(el.listeners)){
20 delete el.listeners;
21 }
22 }
23 // 添加事件
24 function add(el, type, fn){
25 el.listeners = el.listeners || {};
26 var listeners = el.listeners[type] = el.listeners[type] || [];
27 listeners.push(fn);
28 if(!listeners['_handler_']){
29 listeners['_handler_'] = function(e){
30 var evt = e || window.event;
31 for(var i=0,fn; fn=listeners[i++];){
32 fn.call(el, evt);
33 }
34 }
35 el.addEventListener ?
36 el.addEventListener(type, listeners['_handler_'], false) :
37 el.attachEvent('on' + type, listeners['_handler_']);
38 }
39 }
40 // 删除事件
41 function remove(el, type, fn){
42 if(!el.listeners) return;
43 var listeners = el.listeners && el.listeners[type];
44 if(listeners) {
45 _each(listeners, function(i, f){
46 if(f==fn){
47 return listeners.splice(i, 1);
48 }
49 });
50 if(listeners.length == 0){
51 _remove(el,type);
52 }
53 }
54 }
55 //主动触发事件
56 function dispatch(el ,type){
57 try{
58 if(el.dispatchEvent){
59 var evt = document.createEvent('Event');
60 evt.initEvent(type,true,true);
61 el.dispatchEvent(evt);
62 }else if(el.fireEvent){
63 el.fireEvent('on'+type);
64 }
65 }catch(e){};
66 }
67 return {
68 add: add,
69 remove: remove,
70 dispatch: dispatch
71 };
72 }();
相关: