iTakeo

改变attachEvent的this指向,导致无法detachEvent的解决方法。

改变attachEvent的this指向,导致无法detachEvent的解决方法。

我们在给dom元素绑定事件的时候,通常使用下面的方法:

  1. //绑定  
  2. function bind(obj,name,fn){  
  3.     if(obj.addEventListener){  
  4.         obj.addEventListener(name,fn,false);  
  5.     }else if(obj.attachEvent){  
  6.         obj.attachEvent(‘on’+name,fn);  
  7.     };  
  8. };  
  9. //移除  
  10. function unbind(obj,name,fn){  
  11.     if(obj.removeEventListener){  
  12.         obj.removeEventListener(name,fn);  
  13.     }else if(obj.detachEvent){  
  14.         obj.detachEvent(‘on’+name,fn);  
  15.     };  
  16. };  

看似完美,其实在IE8以下中有bug,当在用attachEvent给元素添加事件的时候,默认的this指向是window,而不是元素自身。可以点击下面的div查看。在IE8及以下,this指的是window对象。

  1. var dom = document.getElementById(‘add_ev’);  
  2. bind(dom,’click’,fn);  
  3. function fn(){  
  4.     alert(this)  
  5. };  
点击我

然后我们使用call来改变this指向,用bind也可以,只是bind不支持ie9以下。于是绑定函数改成下面这样。

  1. //绑定    
  2. function bind(obj,name,fn){  
  3.     if(obj.addEventListener){  
  4.         obj.addEventListener(name,fn,false);  
  5.     }else if(obj.attachEvent){  
  6.         obj.attachEvent(‘on’+name,function(){  
  7.             fn.call(obj)  
  8.         });  
  9.     };  
  10. };  

IE中测试没问题,this不再指向window,而指向了自身;但是新问题又来了,使用call,相当于使用了匿名函数,导致detachEvent无法移除事件了,具体点击下面的div,然后点击移除按钮,会发现在IE8以下,无法移除。

  1. var dom = document.getElementById(‘add_ev1’);  
  2. bind(dom,’click’,fn);  
  3. function fn(){  
  4.     alert(this);  
  5. };  
  6. var del = document.getElementById(‘del_ev1’);  
  7. del.onclick = function () {  
  8.     unbind(dom,’click’,fn);  
  9. };  
点击我
移除事件

想要解决这个问题也很简单,有两种方法,一种是在dom上挂载一个属性,另外一种在bind的函数里把call单独拎出来,然后return出去给一个变量。具体请在IE8以下浏览器测试。其他浏览器会看不出效果。

方法一,将bind修改为以下:

  1. //绑定  
  2. function bind(obj,name,fn){  
  3.     var _fn = fn;  
  4.     fn = function(e){  
  5.         _fn.call(obj,e);  
  6.     };  
  7.     obj.addEventListener? obj.addEventListener(name, fn, false):obj.attachEvent(‘on’+name,fn);  
  8.     return fn;    
  9. };  
  1. var dom = document.getElementById(‘add_ev2’);  
  2. //将绑定的赋值给一个变量  
  3. var newFn = bind(dom,’click’,fn);  
  4. function fn(){  
  5.     alert(this);  
  6. };  
  7. var del = document.getElementById(‘del_ev2’);  
  8. del.onclick = function () {  
  9.     //移除的时候,fn函数写这个变量  
  10.     unbind(dom,’click’,newFn);  
  11. };  
点击我
移除事件

方法二,将bind和unbind分别修改如下:

  1. function bind(obj,name,fn){  
  2.     if(obj.addEventListener){    
  3.         obj.addEventListener(name,fn,false);    
  4.     }else if(obj.attachEvent){    
  5.         obj[‘new‘+name] = obj[‘new‘+name] || {};  
  6.         obj[‘new‘+name][‘new‘+fn] = obj[‘new‘+name][‘new‘+fn] || function(){  
  7.             fn.call(obj);  
  8.         };  
  9.         obj.attachEvent(‘on’+name,obj[‘new‘+name][‘new‘+fn]);  
  10.     };  
  11. };  
  12. function unbind(obj,name,fn){  
  13.     if(obj.removeEventListener){    
  14.         obj.removeEventListener(name,fn);    
  15.     }else if(obj.detachEvent){   
  16.         if( obj[‘new‘+name] &&  obj[‘new‘+name][‘new‘+fn]){  
  17.             obj.detachEvent(‘on’+name , obj[‘new‘+name][‘new‘+fn]);  
  18.         };  
  19.     };  
  20. };  
点击我
移除事件



2015/10/15 0 / /
标签:  暂无标签

验证码: 5 + 2 =

回到顶部