事件绑定(终极版)

内容提纲:

1.问题所在

2.设置代码

发文不易,转载注明出处!

 

1.问题所在

现代绑定中W3C使用的是:addEventListener和removeEventListener。IE使用的是attachEvent和detachEvent。我们知道IE的这两个问题多多,并且伴随内存泄漏。所以,解决这些问题非常有必要。

那么我们希望解决非IE浏览器事件绑定哪些问题呢?

1.支持同一元素的同一事件句柄可以绑定多个监听函数;

2.如果在同一元素的同一事件句柄上多次注册同一函数,那么第一次注册后的所有注册都被忽略;

3.函数体内的this指向的应当是正在处理事件的节点(如当前正在运行事件句柄的节点);

4.监听函数的执行顺序应当是按照绑定的顺序执行;

5.在函数体内不用使用 event = event || window.event; 来标准化Event对象;

我们尝试着通过使用传统事件绑定对IE进行封装。

 

2.设置代码

  1 //跨浏览器添加事件绑定
  2 
  3 function addEvent(obj, type, fn) {
  4 
  5        if (typeof obj.addEventListener != 'undefined') {
  6 
  7               obj.addEventListener(type, fn, false);
  8 
  9        } else {
 10 
 11               //创建事件类型的散列表(哈希表)
 12 
 13               if (!obj.events) obj.events = {};
 14 
 15               //创建存放事件处理函数的数组
 16 
 17               if (!obj.events[type]) {
 18 
 19                      obj.events[type] = []; 28 
 29                      //执行事件处理
 30 
 31                      obj['on' + type] = addEvent.exec;
 32 
 33               } else {
 34 
 35                      //同一个注册函数取消计数
 36 
 37                      if (addEvent.array(fn,obj.events[type])) return false;  
 38 
 39               }
 40 
 41               //通过计数器存储
 42 
 43               obj.events[type][addEvent.ID++] = fn;
 44 
 45        }
 46 
 47 }
 48 
 49  
 50 
 51 addEvent.array = function (fn, es){
 52 
 53        for (var i in es) {
 54 
 55               if (es[i] == fn) return true;
 56 
 57        }
 58 
 59        return false;
 60 
 61 }
 62 
 63  
 64 
 65 //每个事件处理函数的ID计数器
 66 
 67 addEvent.ID = 0;
 68 
 69  
 70 
 71 //事件处理函数调用
 72 
 73 addEvent.exec = function (event) {
 74 
 75        var e = event || addEvent.fixEvent(window.event);
 76 
 77        var es = this.events[e.type];
 78 
 79        for (var i in es) {
 80 
 81               es[i].call(this, e);
 82 
 83        }
 84 
 85 };
 86 
 87  
 88 
 89 //获取IE的event,兼容W3C的调用
 90 
 91 addEvent.fixEvent = function (event) {
 92   //为event添加preventDefault方法
 93        event.preventDefault = addEvent.fixEvent.preventDefault;
 95        event.stopPropagation = addEvent.fixEvent.stopPropagation;
 96 
 97        return event;
 98 
 99 };
100 
101  
102 
103 //兼容IE和W3C阻止默认行为
104 
105 addEvent.fixEvent.preventDefault = function () {
106 
107        this.returnValue = false;
108 
109 };
110 
111  
112 
113 //兼容IE和W3C取消冒泡
114 
115 addEvent.fixEvent.stopPropagation = function () {
116 
117        this.cancelBubble = true;
118 
119 };
120 
121  
122 
123 //跨浏览器删除事件
124 
125 function removeEvent(obj, type, fn) {
126 
127        if (typeof obj.removeEventListener != 'undefined') {
128 
129               obj.removeEventListener(type, fn, false);
130 
131        } else {
132 
133               var es = obj.events[type];
134 
135               for (var i in es) {
136 
137                      if (es[i] == fn) {
138 
139                             delete obj.events[type][i];
140 
141                      }
142 
143               }
144 
145        }
146 
147 }
原文地址:https://www.cnblogs.com/ttcc/p/3963457.html