找回密码
 新建账号

[JS] addEventListener attachEvent和解决IE 6 7 8 this指向错误

[复制链接]
php 发表于 2014/4/13 01:17 | 显示全部楼层 |阅读模式
标准浏览器中可以使用addEventListener()函数来给DOM元素绑定事件,使用removeEventListener()函数移除事件绑定,而IE6 IE7 IE8不支持addEventListener()和removeEventListener(),只能使用attachEvent()和detachEvent()方法。IE从IE9开始支持addEventListener和removeEventListener.
addEventListener()和attachEvent()的区别主要有以下几点:
  • addEventListener(type, handler, capture)有三个参数,其中type是事件名称,如click,handler是事件处理函数,capture是否使用捕获,是一个布尔值,默认值为false,第三个参数可以省略不写。
    attachEvent('on' + type, handler)有两个参数,其中type是事件名称,如click,第一个参数必须是onxxxx,handler是事件处理函数,IE6 IE7 IE8不支持事件捕获,只支持事件冒泡,所以不存在第三个参数。
    关于事件冒泡:如果一个元素和它的各层上级素都设置了相同的事件,比如click事件,那么冒泡是指,事件触发时,首先触发最底层元素的事件,然后依次逐层递进触发上一级元素的相同事件,就像泡泡从水底冒到水面一样。
    而与事件冒泡相反,事件捕获的顺序是,从页面的根元素开始依次逐层向下级触发事件。
    IE6-8只支持事件冒泡不支持事件捕获,Google Chrome/Firefox/Safari/Opera等标准现代浏览器支持事件捕获和事件冒泡。
    如果只想在最底层执行事件处理函数,阻止事件向上层元素冒泡,也就是说如果要阻止事件冒泡,标准浏览器可以使用event.stopPropagation(),IE6 7 8可以使用设置window.event.cancelBubble=true来处理
  • addEventListener如果绑定多个事件处理函数,事件触发时按绑定顺序依次调用事件处理函数,attachEvent绑定多个事件处理函数,事件触发时从最后一个函数依次逆向调用处理函数。
  • 在IE6 IE7 IE8浏览器中,使用了attachEvent或detachEvent后事件处事函数里面的this指向window对象,而不是触发事件的元素,文末有解决方案。
  • 如果一个事件在绑定以后又有解除绑定的需要,可以使用removeEventListener(),参数和addEventListener一样,IE6 IE7 IE8使用detachEvent()方法,参数和attachEvent()一样,注意,想要移除绑定的事件处理函数,绑定事件时不能使用匿名函数,而需要将事件处事函数单独写成一个函数。否则无法移除绑定的事件处理函数,因为只有绑定的事件处理函数才能移除,而匿名函数和匿名函数是互不相同的,即使两个匿名函数代码完全一样,本质上同一匿名函数的代码写两次也是两个不同的函数。
    下面以addEventListener为例
    1.         <a id="xc">点击</a>
    2.         <script type="text/javascript">
    3.                 function handler(){
    4.                         alert(this.innerHTML);
    5.                 }
    6.                 var object=document.getElementById('xc');
    7.                 xc.addEventListener('click',handler,false);//添加事件处理函数
    8.                 xc.removeEventListener('click',handler,false);//移除事件处理函数
    9.                 /*下面这种使用匿名函数的方式添加的事件处理函数是不能移除的,因为两个匿名函数虽然代码一样,但他们是两个不同的函数
    10.                 xc.addEventListener('click',function(){
    11.                         alert(this.innerHTML);
    12.                 },false);
    13.                 xc.removeEventListener('click',function(){
    14.                         alert(this.innerHTML);
    15.                 },false);
    16.                 */
    17.         </script>
    复制代码

  • 所添加的事件必须是事件对象支持的事件,比如给window对象添加click事件就不会成功,因为window没有click事件
  • 解决IE6 IE7 IE8 attchEvent this指向window的方法:
   要解决IE6 IE7 IE8 attachEvent this指向错误,有至少以下三种方法:
  • 使用事件处理函数.apply(事件对象,arguments),代码如下
        以下代码仅适用于IE6 IE7 IE8
     这种方式的缺点是绑定的事件无法取消绑定,原因上面已经说了,匿名函数和匿名函数之间是互不相等的。
    1.         <a id="xc">点击</a>
    2.         <script type="text/javascript">
    3.                 var object=document.getElementById('xc');
    4.                 function handler(){
    5.                         alert(this.innerHTML);
    6.                 }
    7.                 object.attachEvent('onclick',function(){
    8.                         handler.call(object,arguments);
    9.                 });
    10.         </script>
    复制代码

  • 使用事件源代替this关键字
    以下代码仅适用于IE6 IE7 IE8,这种方式完全忽略this关键字,但写起来稍显麻烦。
    1.         <a id="xc">点击</a>
    2.         <script type="text/javascript">
    3.                 function handler(e){
    4.                         e=e||window.event;
    5.                         var _this=e.srcElement||e.target;
    6.                         alert(_this.innerHTML);
    7.                 }
    8.                 var object=document.getElementById('xc');
    9.                 object.attachEvent('onclick',handler);
    10.         </script>
    复制代码

  • 自己写一个函数完全代替attachEvent/detachEvent,并且支持所有主流浏览器、解决IE6 IE7 IE8事件绑定导致的先绑定后执行问题。
    下面是完美兼容addEventListener/removeEventListener和attachEvent/detachEvent的函数,支持Google Chrome/Firefox/Safari/Opera/IE 6 7 8 9 10 11等所有主流浏览器,能够完美解决IE6 IE7 IE8 this指向错误,能够纠正IE6 IE7 IE8中事件先绑定后执行的错误。
    为了避免代码被编辑器修改,请下载附件测试。不要直接复制下面的代码。
    注意,本函数是全局函数,而不是DOM对象的成员方法。
    1. <a id="xc">点击</a>
    2. <script type="text/javascript">
    3.         /*
    4.          * 添加事件处理程序
    5.          * @param object object 要添加事件处理程序的元素
    6.          * @param string type 事件名称,如click
    7.          * @param function handler 事件处理程序,可以直接以匿名函数的形式给定,或者给一个已经定义的函数名。匿名函数方式给定的事件处理程序在IE6 IE7 IE8中可以移除,在标准浏览器中无法移除。
    8.          * @param boolean remove 是否是移除的事件,本参数是为简化下面的removeEvent函数而写的,对添加事件处理程序不起任何作用
    9.         */
    10.         function addEvent(object, type, handler, remove){
    11.                 if(typeof object!='object'||typeof handler!='function') return;
    12.                 try{
    13.                         object[remove?'removeEventListener':'addEventListener'](type,handler,false);
    14.                 }catch(e){
    15.                         var xc='_'+type;
    16.                         object[xc]=object[xc]||[];
    17.                         if(remove){
    18.                                 var l=object[xc].length;
    19.                                 for(var i=0;i<l;i++){
    20.                                         if(object[xc][i].toString()===handler.toString()) object[xc].splice(i,1);
    21.                                 }
    22.                         }else{
    23.                                 var l=object[xc].length;
    24.                                 var exists=false;
    25.                                 for(var i=0;i<l;i++){                                                
    26.                                         if(object[xc][i].toString()===handler.toString()) exists=true;
    27.                                 }
    28.                                 if(!exists) object[xc].push(handler);
    29.                         }
    30.                         object['on'+type]=function(){
    31.                                 var l=object[xc].length;
    32.                                 for(var i=0;i<l;i++){
    33.                                         object[xc][i].apply(object,arguments);
    34.                                 }
    35.                         }
    36.                 }
    37.         }
    38.         /*
    39.          * 移除事件处理程序
    40.         */
    41.         function removeEvent(object,type,handler){
    42.                 addEvent(object,type,handler,true);
    43.         }
    44. </script>
    45. <script type="text/javascript">
    46.         function handler(){
    47.                 alert(this.innerHTML);
    48.         }
    49.         var object=document.getElementById('xc');
    50.         addEvent(object,'click',handler);
    51.         //如果要测试绑定事件,请先删除下面这一行。
    52.         removeEvent(object,'click',handler);
    53. </script>
    复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?新建账号

×
cl5168 发表于 2016/8/26 13:56 | 显示全部楼层
大神,这个怎么引用啊?

手机版|轻松E站

GMT+8, 2024/3/29 21:08

快速回复 返回顶部 返回列表