阿西河

所有教程

公众号
🌙
阿西河前端的公众号

我的收藏

    最近访问  (文章)

      教程列表

      抓包专区
      测试专区

      JavaScript DOM2事件绑定的兼容性总结

      DOM2事件绑定的兼容性总结

      <!DOCTYPE html>
      <html>
      <head lang="en">
          <meta charset="UTF-8">
          <title></title>
      </head>
      <body>
      <ol>
          **DOM2事件绑定的兼容性总结,IE是指低版本IE**:
      
      
          1. 方法不同,一个是(addEventListener/removeEventListener),IE是(attachEvent/detachEvent)
          2. IE里被绑定上的方法,this关键字指向window;
          3. IE里执行的顺序是混乱的
          4. IE里的方法是可以被重复绑定的;
          5. 事件对象本身,IE是全局的时间对象window.event;其他的是系统自动传的
          6. 事件源:标准浏览器是e.target;IE是srcElement;
          7. 阻止事件的默认行为:标准浏览器是e.preventDefault(),IE是returnValue=false;
          8. 在所有浏览器中,如果用DOM0的方式来绑定,方法里面用return false也可以阻止默认行为的;这个是可以阻止DOM0的,如果是DOM2级的就不可以了
          8. 阻止事件的传播:标准浏览器是e.stopPropagation();IE是cancelBubble=true;
          9. e.pageX,e.pageY,这两个属性IE不支持;
          10. IE不支持捕获,只能支持冒泡;所以标准浏览器绑定和解绑第三个参数是false,第三个参数不写,也是没问题的;
      </ol>
      </body>
      </html>
      

      兼容性解决this关键字

      <!DOCTYPE html>
      <html>
      <head lang="en">
          <meta charset="UTF-8">
          <title>this关键字</title>
          <style>
              #div1{width: 100px;height: 100px;background: orange;}
          </style>
      </head>
      <body>
      <div id="div1"></div>
      </body>
      </html>
      <script>
          var oDiv=document.getElementById("div1");
      
      
      
      
          function bind1(ele,type,fn){
              if(ele.addEventListener){
                  ele.addEventListener(type,fn);
              }else{
                  //解决关键字,与call,apply有关
                  //ele.attachEvent("on"+type,fn.call(ele));//这样不可以的,因为会直接执行;
                  ele.attachEvent("on"+type,function(){fn.call(ele)});//改变fn的this关键字;
              }
          };
          function unbind1(ele,type,fn){
              if(ele.removeEventListener){
                  ele.removeEventListener(type,fn,false);
              }else{
                  ele.detachEvent("on"+type,fn)
              }
          }
          /*改1的,解决了this关键字问题,但是解绑的时候,解除不掉了*/
          /*改2*/
          function bind2(ele,type,fn){
              if(ele.addEventListener){
                  ele.addEventListener(type,fn);
              }else{
                  var fnTemp=function(){fn.call(ele)};//解决fn的this关键字
                  var oBind=ele.myBind;
                  if(!oBind){//避免多次创建,防止覆盖原来第一次创建的数组;
                      oBind=[];
                  }
                  for (var i=0;i< oBind.length;i++){//防止重复绑定的;
                      if(oBind[i].flag==fn){
                          return;
                      }
                  }
                  oBind.push(fnTemp);
                  fnTemp.flag=fn;//flag是识别符号;是为了解绑的时候,可以找到解绑目标;因为fn是函数,属于引用类型数据,不能和fn相等;fn!==fn;所以在上面加了一个flag;方面解绑来解除
                  ele.attachEvent("on"+type,fnTemp);//改变fn的this关键字;
              }
          };
          function unbind2(ele,type,fn){
              if(ele.removeEventListener){
                  ele.removeEventListener(type,fn,false);
              }else{
                  var oBind=ele.myBind;
                  if(oBind&& oBind.length){
                      for(var i=0;i< oBind.length;i++){
                          if(oBind[i].flag===fn){//a[i]和fnTemp是一样的;a[i].flag相当于fnTemp.flag
                              ele.detachEvent("on"+type,oBind[i]);//a[i]就是化妆后的fn;
                              oBind.splice(i,1);//一个方法只能绑定一个一次,所以要删除绑定过的;
                              return;
      
                          }
                      }
                  }
              }
          };
          /*改2里面如果给oDiv的onclick绑定fn1,那么在oDiv的onmouseover就不能继续绑定fn1了,因为他们公用一个数组*/
      
          /*下面是成功的了,最终的*/
          /*****改3*/
          function bind3(ele,type,fn){
              if(ele.addEventListener){
                  ele.addEventListener(type,fn);
              }else{
                  var fnTemp=function(){fn.call(ele)};//解决fn的this关键字
                  /*下面是标示,是为了解绑做铺垫的;*/
                  if(!ele["myBind"+type]){//避免多次创建,防止覆盖原来第一次创建的数组;
                      ele["myBind"+type]=[];
                  }
                  var oBind=ele["myBind"+type];
                  for (var i=0;i< oBind.length;i++){//防止重复绑定的;
                      if(oBind[i].flag==fn){
                          return;
                      }
                  }
                  oBind.push(fnTemp);
                  fnTemp.flag=fn;
                  ele.attachEvent("on"+type,fnTemp);
              }
          };
          function unbind3(ele,type,fn){
              if(ele.removeEventListener){
                  ele.removeEventListener(type,fn);
                  console.log("标准浏览器的"+type+"已经解绑!")
              }else{
                  console.log("IE6/7/8的"+type+"已经解绑!")
                  var oBind=ele["myBind"+type];
                  if(oBind&& oBind.length){
                      for(var i=0;i< oBind.length;i++){
                          /*下面是确定要解绑的fn;*/
                          if(oBind[i].flag===fn){
                              ele.detachEvent("on"+type,oBind[i]);
                              oBind.splice(i,1);
                              return;
                          }
                      }
                  }
              }
          };
      
      
          bind3(oDiv,"click",fn1);
          bind3(oDiv,"mouseover",fn1);
          var num=0;
          function fn1(){
              num++;
              this.innerHTML="改变this关键字"+num;
              if(num==5){
                  console.log("解除绑定的函数");
                  unbind3(oDiv,"click",fn1);
                  unbind3(oDiv,"mouseover",fn1);
              }
          }
      
          function fn4(){
              num+=1;
              if(num==3){
                  unbind(this,"click",fn1);//移除
              }
              console.log("4");
          };
      </script>
      

      兼容性解决执行顺序

      <!DOCTYPE html>
      <html>
      <head lang="en">
          <meta charset="UTF-8">
          <title>执行顺序</title>
          <style>
              #div1{width: 100px;height: 100px;background: orange;}
          </style>
      </head>
      <body>
      <div id="div1"></div>
      低版本的IE事件,如果超过9个就会混乱了;9个内是倒序的;
      </body>
      </html>
      <script>
          /*下面是解决好this关键字的了,最终的*/
          function bind3(ele,type,fn){
              if(ele.addEventListener){
                  ele.addEventListener(type,fn);
              }else{
                  var fnTemp=function(){fn.call(ele)};//解决fn的this关键字
                  /*下面是标示,是为了解绑做铺垫的;*/
                  if(!ele["myBind"+type]){//避免多次创建,防止覆盖原来第一次创建的数组;
                      ele["myBind"+type]=[];
                  }
                  var oBind=ele["myBind"+type];
                  for (var i=0;i< oBind.length;i++){//防止重复绑定的;
                      if(oBind[i].flag==fn){
                          return;
                      }
                  }
                  oBind.push(fnTemp);
                  fnTemp.flag=fn;
                  ele.attachEvent("on"+type,fnTemp);
              }
          };
          function unbind3(ele,type,fn){
              if(ele.removeEventListener){
                  ele.removeEventListener(type,fn);
                  console.log("标准浏览器的"+type+"已经解绑!")
              }else{
                  console.log("IE6/7/8的"+type+"已经解绑!")
                  var oBind=ele["myBind"+type];
                  if(oBind&& oBind.length){
                      for(var i=0;i< oBind.length;i++){
                          /*下面是确定要解绑的fn;*/
                          if(oBind[i].flag===fn){
                              ele.detachEvent("on"+type,oBind[i]);
                              oBind.splice(i,1);
                              return;
                          }
                      }
                  }
              }
          };
      
      
      
          /*下面是解决执行顺序的方案IE678*/
      
          var oDiv=document.getElementById("div1");
          var type="click";
          oDiv["aEvent"+type]=[];
          oDiv["aEvent"+type].push(fn1);
          oDiv["aEvent"+type].push(fn2);
          oDiv["aEvent"+type].push(fn3);
          oDiv["aEvent"+type].push(fn4);
          oDiv["aEvent"+type].push(fn5);
          oDiv["aEvent"+type].push(fn6);
          oDiv["aEvent"+type].push(fn7);
          oDiv["aEvent"+type].push(fn8);
          oDiv["aEvent"+type].push(fn9);
          oDiv["aEvent"+type].push(fn10);
      
          bind3(oDiv,type,run);
          /*绑定给run;然后由函数run统一来调*/
          function run(){
              console.log("执行run方法");
              var a=this["aEvent"+window.event.type];//因为做IE的,所以写window.event
              for(var i=0;i< a.length;i++){
                  //a[i]();//这样是不行的虽然顺序解决了,但是IE的this还是不对了;
                  a[i].call(this);//这样就可以了
              }
          }
      
      
      
          function fn1(){console.log("执行函数fn1")}
          function fn2(){console.log("执行函数fn2")}
          function fn3(){console.log("执行函数fn3")}
          function fn4(){console.log("执行函数fn4")}
          function fn5(){console.log("执行函数fn5")}
          function fn6(){console.log("执行函数fn6")}
          function fn7(){console.log("执行函数fn7")}
          function fn8(){console.log("执行函数fn8")}
          function fn9(){console.log("执行函数fn9")}
          function fn10(){console.log("执行函数fn10")}
      </script>
      

      兼容性解决执行顺序–2封装

      <!DOCTYPE html>
      <html>
      <head lang="en">
          <meta charset="UTF-8">
          <title>执行顺序</title>
          <style>
              #div1{width: 100px;height: 100px;background: orange;}
          </style>
      </head>
      <body>
      <div id="div1"></div>
      低版本的IE事件,如果超过9个就会混乱了;9个内是倒序的;
      </body>
      </html>
      <script>
          /*下面是解决好this关键字的了,最终的*/
          function bind3(ele,type,fn){
              if(ele.addEventListener){
                  ele.addEventListener(type,fn);
              }else{
                  var fnTemp=function(){fn.call(ele)};//解决fn的this关键字
                  /*下面是标示,是为了解绑做铺垫的;*/
                  if(!ele["myBind"+type]){//避免多次创建,防止覆盖原来第一次创建的数组;
                      ele["myBind"+type]=[];
                  }
                  var oBind=ele["myBind"+type];
                  for (var i=0;i< oBind.length;i++){//防止重复绑定的;
                      if(oBind[i].flag==fn){
                          return;
                      }
                  }
                  oBind.push(fnTemp);
                  fnTemp.flag=fn;
                  ele.attachEvent("on"+type,fnTemp);
              }
          };
          function unbind3(ele,type,fn){
              if(ele.removeEventListener){
                  ele.removeEventListener(type,fn);
                  console.log("标准浏览器的"+type+"已经解绑!")
              }else{
                  console.log("IE6/7/8的"+type+"已经解绑!")
                  var oBind=ele["myBind"+type];
                  if(oBind&& oBind.length){
                      for(var i=0;i< oBind.length;i++){
                          /*下面是确定要解绑的fn;*/
                          if(oBind[i].flag===fn){
                              ele.detachEvent("on"+type,oBind[i]);
                              oBind.splice(i,1);
                              return;
                          }
                      }
                  }
              }
          };
      
      
      
          /*下面是解决一个元素同一类似事件的执行顺序*/
      
          var oDiv=document.getElementById("div1");
          function on(ele,type,fn){
              if(!ele["aEvent"+type]){
                  ele["aEvent"+type]=[];
              }
              var aryEvent=ele["aEvent"+type];
              for(var i=0;i<aryEvent.length;i++){//防止同一个方法被同事件绑定;
                  if(aryEvent[i]==fn)return;
              }
              aryEvent.push(fn);
              bind3(ele,type,run);//只会执行一次
          }
      
          function off(ele,type,fn){
              if(ele["aEvent"+type]){
                  var aryEvent=ele["aEvent"+type];
                  for(var i=0;i<aryEvent.length;i++){
                      if(a[i]==fn){
                          aryEvent.splice(i,1);//会造成数组塌陷;
                          return;
                      }
                  }
              }
          }
      
      
      
          on(oDiv,"click",fn1);
          on(oDiv,"click",fn2);
          on(oDiv,"click",fn3);
          on(oDiv,"click",fn4);
          on(oDiv,"click",fn5);
          on(oDiv,"click",fn6);
          on(oDiv,"click",fn7);
          on(oDiv,"click",fn8);
          on(oDiv,"click",fn9);
          on(oDiv,"click",fn10);
      
      
          function run(e){
              e=e||window.event;
              var a=this["aEvent"+e.type];
              for(var i=0;i< a.length;i++){
                  a[i].call(this);
              }
          }
      
      
      
          function fn1(){console.log("执行函数fn1")}
          function fn2(){console.log("执行函数fn2")}
          function fn3(){console.log("执行函数fn3")}
          function fn4(){console.log("执行函数fn4")}
          function fn5(){console.log("执行函数fn5")}
          function fn6(){console.log("执行函数fn6")}
          function fn7(){console.log("执行函数fn7")}
          function fn8(){console.log("执行函数fn8")}
          function fn9(){console.log("执行函数fn9")}
          function fn10(){console.log("执行函数fn10")}
      </script>
      

      off和run执行时数组塌陷问题

      <!DOCTYPE html>
      <html>
      <head lang="en">
          <meta charset="UTF-8">
          <title>执行顺序</title>
          <style>
              #div1{width: 100px;height: 100px;background: orange;}
          </style>
      </head>
      <body>
      <div id="div1"></div>
      低版本的IE事件,如果超过9个就会混乱了;9个内是倒序的;
      </body>
      </html>
      <script>
          /*下面是解决好this关键字的了,最终的*/
          function bind3(ele,type,fn){
              if(ele.addEventListener){
                  ele.addEventListener(type,fn);
              }else{
                  var fnTemp=function(){fn.call(ele)};//解决fn的this关键字
                  /*下面是标示,是为了解绑做铺垫的;*/
                  if(!ele["myBind"+type]){//避免多次创建,防止覆盖原来第一次创建的数组;
                      ele["myBind"+type]=[];
                  }
                  var oBind=ele["myBind"+type];
                  for (var i=0;i< oBind.length;i++){//防止重复绑定的;
                      if(oBind[i].flag==fn){
                          return;
                      }
                  }
                  oBind.push(fnTemp);
                  fnTemp.flag=fn;
                  ele.attachEvent("on"+type,fnTemp);
              }
          };
          function unbind3(ele,type,fn){
              if(ele.removeEventListener){
                  ele.removeEventListener(type,fn);
                  console.log("标准浏览器的"+type+"已经解绑!")
              }else{
                  console.log("IE6/7/8的"+type+"已经解绑!")
                  var oBind=ele["myBind"+type];
                  if(oBind&& oBind.length){
                      for(var i=0;i< oBind.length;i++){
                          /*下面是确定要解绑的fn;*/
                          if(oBind[i].flag===fn){
                              ele.detachEvent("on"+type,oBind[i]);
                              oBind.splice(i,1);
                              return;
                          }
                      }
                  }
              }
          };
          /*下面是解决一个元素同一类似事件的执行顺序*/
      
          var oDiv=document.getElementById("div1");
          function on(ele,type,fn){
              if(!ele["aEvent"+type]){
                  ele["aEvent"+type]=[];
              }
              var aryEvent=ele["aEvent"+type];
              for(var i=0;i<aryEvent.length;i++){//防止同一个方法被同事件绑定;
                  if(aryEvent[i]==fn)return;
              }
              aryEvent.push(fn);
              bind3(ele,type,run);//只会执行一次
          }
      
          function off(ele,type,fn){
              if(ele["aEvent"+type]){
                  var aryEvent=ele["aEvent"+type];
                  for(var i=0;i<aryEvent.length;i++){
                      if(a[i]==fn){
      //                    aryEvent.splice(i,1);//数组塌陷
                          a[i]=null;
                          return;
                      }
                  }
              }
          }
      
      
          function run(e){
              e=e||window.event;
              var a=this["aEvent"+e.type];
              for(var i=0;i< a.length;){
                  /*下面是防止数组塌陷的*/
                  if(typeof a[i]="function"){
                      a[i].call(this);
                      i++
                  }else{
                      /*如果是空的,删掉;不删也是可以的*/
                      a.splice(i,1);
                  }
              }
          }
      
          on(oDiv,"click",fn1);
          on(oDiv,"click",fn2);
          on(oDiv,"click",fn3);
          on(oDiv,"click",fn4);
          on(oDiv,"click",fn5);
          on(oDiv,"click",fn6);
          on(oDiv,"click",fn7);
          on(oDiv,"click",fn8);
          on(oDiv,"click",fn9);
          on(oDiv,"click",fn10);
      
      
      
      
      
      
          function fn1(){console.log("执行函数fn1")}
          function fn2(){console.log("执行函数fn2")}
          function fn3(){console.log("执行函数fn3")}
          function fn4(){console.log("执行函数fn4")}
          function fn5(){console.log("执行函数fn5")}
          function fn6(){console.log("执行函数fn6")}
          function fn7(){console.log("执行函数fn7")}
          function fn8(){console.log("执行函数fn8")}
          function fn9(){console.log("执行函数fn9")}
          function fn10(){console.log("执行函数fn10")}
      </script>
      

      解决全部兼容性问题

      <!DOCTYPE html>
      <html>
      <head lang="en">
          <meta charset="UTF-8">
          <title>执行顺序</title>
          <style>
              #div1{width: 100px;height: 100px;background: orange;}
          </style>
      </head>
      <body>
      <div id="div1">
          <a href="http://broszhu.com/">朱安邦的博客</a>
      </div>
      </body>
      </html>
      <script>
          var oDiv=document.getElementById("div1");
          var oA=oDiv.getElementsByTagName("a")[0];
      
          //on(oA,"click",fnTest);//只能监测A的
          on(document.documentElement,"click",fnTest);//可以检测DIV,BODY,HTML;
      
      
          function fnTest(e){
              /*不需要写window.event了,因为在run里已经解决了*/
              console.log(this);
              console.log(e.target.nodeName);
              e.preventDefault();//阻止默认行为;
              e.stopPropagation();//不会传播
          }
      
              /*下面是解决好this关键字的了,最终的*/
          function bind3(ele,type,fn){
              if(ele.addEventListener){
                  ele.addEventListener(type,fn);
              }else{
                  var fnTemp=function(){fn.call(ele)};//解决fn的this关键字
                  if(!ele["myBind"+type]){
                      ele["myBind"+type]=[];
                  }
                  var oBind=ele["myBind"+type];
                  for (var i=0;i< oBind.length;i++){//防止重复绑定的;
                      if(oBind[i].flag==fn){
                          return;
                      }
                  }
                  oBind.push(fnTemp);
                  fnTemp.flag=fn;
                  ele.attachEvent("on"+type,fnTemp);
              }
          };
          function unbind3(ele,type,fn){
              if(ele.removeEventListener){
                  ele.removeEventListener(type,fn);
                  console.log("标准浏览器的"+type+"已经解绑!")
              }else{
                  console.log("IE6/7/8的"+type+"已经解绑!")
                  var oBind=ele["myBind"+type];
                  if(oBind&& oBind.length){
                      for(var i=0;i< oBind.length;i++){
                          /*下面是确定要解绑的fn;*/
                          if(oBind[i].flag===fn){
                              ele.detachEvent("on"+type,oBind[i]);
                              oBind.splice(i,1);
                              return;
                          }
                      }
                  }
              }
          };
      
      
          /*下面是解决一个元素同一类似事件的执行顺序*/
          function on(ele,type,fn){
              if(!ele["aEvent"+type]){
                  ele["aEvent"+type]=[];
              }
              var aryEvent=ele["aEvent"+type];
              for(var i=0;i<aryEvent.length;i++){//防止同一个方法被同事件绑定;
                  if(aryEvent[i]==fn)return;
              }
              aryEvent.push(fn);
              bind3(ele,type,run);//只会执行一次
          }
      
          function off(ele,type,fn){
              if(ele["aEvent"+type]){
                  var aryEvent=ele["aEvent"+type];
                  for(var i=0;i<aryEvent.length;i++){
                      if(a[i]==fn){
      //                    aryEvent.splice(i,1);//数组塌陷解决
                          a[i]=null;
                          return;
                      }
                  }
              }
          }
      
      
          /*事件兼容性问题,都在run上解决好*/
          function run(e){
              e=e||window.event;
              if(!e.target){
                  e.target= e.srcElement;
                  e.pageX=(document.documentElement.scrollLeft||document.body.scrollLeft)+ e.clientX;
                  e.pageY=(document.documentElement.scrollTop||document.body.scrollTop)+ e.clientY;
                  e.stopPropagation=function(){e.cancelBubble=true;}//阻止事件传播;
                  e.preventDefault=function(){e.returnValue=false;}//阻止事件默认行为;
              }
              /*上面是IE不支持的*/
      
              var a=this["aEvent"+e.type];
              for(var i=0;i< a.length;){
                  /*下面是防止数组塌陷的*/
                  if(typeof a[i]=="function"){
                      //a[i].call(this);//this指向当前被绑定元素;
                      a[i].call(this,e);//this后面加e;就解决了e的兼容性问题;因为想this主体传了e;具体的函数就不需要再解决e的兼容了;
                      i++;
                  }else{
                      /*如果是空的,删掉;不删也是可以的*/
                      a.splice(i,1);
                  }
              }
          }
      
      </script>
      
      目录
      目录