上一篇中的add有个问题,对同一类型事件添加多个hanlder时,IE6/7/8下会无序,如
<div id="d1" style="width:200px;height:200px;background:gold;"></div> <script type="text/javascript"> var el = document.getElementById('d1'); function handler1(){alert('1');} function handler2(){alert('2');} function handler3(){alert('3');} function handler4(){alert('4');} function handler5(){alert('5');} E.add(el, 'click', handler1); E.add(el, 'click', handler2); E.add(el, 'click', handler3); E.add(el, 'click', handler4); E.add(el, 'click', handler5); </script>
IE9/Firefox/Safari/Chomre/Opera会依次输出1,2,3,4,5。但IE6/7/8中则不一定。为解决所有浏览器中多个事件handler有序执行,我们需要一个队列来管理所有的handler。
这次,把所有的内部细节封装在一个匿名函数中,该函数执行完毕后返回如上一篇接口相同的方法。另外
E = function(){ function _isEmptyObj(obj){ for(var a in obj){ return false; } return true; } function _each(ary, callback){ for(var i=0,len=ary.length; i<len;){ callback(i, ary[i]) ? i=0 : i++; } } function _remove(el, type){ var handler = el.listeners[type]['_handler_']; el.removeEventListener ? el.removeEventListener(type, handler, false) : el.detachEvent('on'+type, handler); delete el.listeners[type]; if(_isEmptyObj(el.listeners)){ delete el.listeners; } } // 添加事件 function add(el, type, fn){ el.listeners = el.listeners || {}; var listeners = el.listeners[type] = el.listeners[type] || []; listeners.push(fn); if(!listeners['_handler_']){ listeners['_handler_'] = function(e){ var evt = e || window.event; for(var i=0,fn; fn=listeners[i++];){ fn.call(el, evt); } } el.addEventListener ? el.addEventListener(type, listeners['_handler_'], false) : el.attachEvent('on' + type, listeners['_handler_']); } } // 删除事件 function remove(el, type, fn){ if(!el.listeners) return; var listeners = el.listeners && el.listeners[type]; if(listeners) { _each(listeners, function(i, f){ if(f==fn){ return listeners.splice(i, 1); } }); if(listeners.length == 0){ _remove(el,type); } } } //主动触发事件 function dispatch(el ,type){ try{ if(el.dispatchEvent){ var evt = document.createEvent('Event'); evt.initEvent(type,true,true); el.dispatchEvent(evt); }else if(el.fireEvent){ el.fireEvent('on'+type); } }catch(e){}; } return { add: add, remove: remove, dispatch: dispatch }; }();
相关: