• JavaScript跨浏览器绑定事件函数的优化


    转载自:http://www.cnblogs.com/yugege/p/5169998.html

     JavaScript作为一门基于事件驱动的语言(特别是用在DOM操作的时候),我们常常需要为DOM绑定各种各样的事件。然而,由于低版本的IE的不给力,在绑定事件和移除事件监听上都与众不同,我们常常需要自己封装一个跨浏览器绑定(移除)事件的函数。跨浏览器添加(移除)DOM事件的一种非常经典的实现代码如下:

    复制代码
    //跨浏览器添加事件
    function addHandler(target, eventType, handler) {
      if(target.addEventListener) { //DOM2 events
        target.addEventListener(eventType, handler, false);
      } else { //IE
        target.attachEvent("on" + eventType, handler);
      }
    }
     
    //跨浏览器移除事件
    function removeHanler(target, eventType, handler) {
      if(target.removeEventListener) { //DOM2 events
        target.removeEventListener(eventType, handler, false);
      } else { //IE
        target.detachEvent("on", eventType, handler);
      }
    }
    复制代码

        上面代码的实现思路是,首先判断浏览器是否支持DOM2的事件,如果支持,就用addEventListener()进行添加事件,用removeEventListener来移除事件。如果不支持,那么默认就是低版本的ie浏览器了,并使用ie特有的方法。

        乍一看,上面的代码好像已经充分优化了。隐藏的性能问题在于每次函数调用时都会做重复工作——检测浏览器的类型。这是比较消耗性能,特别是你绑定大量事件,反复调用的时候。事实上,这是不必要的,我们只需要判断一次就行的了。因为一旦页面加载完成后,浏览器的类型已经是确定了的,不可能说,现在是IE,然后浏览着浏览着突然就会变成了chrome的了。所以,我们应该对上面代码进行优化,使其只需要检测一次浏览器。有两种方法可以实现只检测一次,下面分别来探讨一下这两种方法。
      第一种是,在第一次调用添加(移除)事件函数的时候,检测并决定使用哪种方法来绑定或者移除事件,然后重写函数,用一个包含正确操作的新的函数覆盖旧的函数,并且在旧的函数最后调用该这个新的函数。上面代码改写后如下:
    复制代码
    //添加事件
    function addHandler(target, eventType, handler) {
     
      //检测浏览器类型,并且重写addHanler方法
      if(target.addEventListener) { //DOM2
        addHandler = function(target, eventType, handler) {
          target.addEventListener(eventType, handler, false);
        };
      } else { //IE
        addHandler = function(target, eventType, handler) {
          target.attachEvent("on" + eventType, handler);
        };
      }
       
      //调用新的函数
      addHandler(target, eventType, handler);
    }
     
    //移除事件removeHanler
    function removeHandler(target, eventType, handler) {
     
      //检测浏览器类型,并且重写removeHandler方法
      if(target.removeEventListener) { //DOM2
        removeHandler = function(target, eventType, handler) {
          target.removeEventListener(eventType, handler, false);
        };
      } else { //IE
        removeHandler = function(target, eventType, handler) {
          target.detachEvent("on" + eventType, handler);
        };
      }
     
      //调用新的函数
      removeHandler(target, eventType, handler);
    }
    复制代码

        需要注意的是,我们在两个函数的最后一行,都调用了被重写了的新函数,比如addHandler(target, eventType, handler);和removeHandler(target, eventType,handler);这是必要的,因为我们用新的函数覆盖了旧的函数,必须要在旧的函数里调用新的函数它才会执行一次。

        还有一种优化方法是,提前检测浏览器类型,并把正确的操作函数赋值给一个变量(或者说是使用函数表达式)。我们可以使用一个三目条件运算符(?...:)来实现,代码如下:
    复制代码
    //绑定事件
    var addHandler = document.body.addEventListener ?
              function(target, eventType, handler) { //DOM2
                target.addEventListener(eventType, handler,false);
              } :
              function(target, eventType, handler) { //IE
                target.attachEvent("on" + eventType, handler);
              };
    //移除事件 var removeHandler = document.body.removeEventListener ?             function(target, eventType, handler) { //DOM2               target.removeEventListener(eventType, handler, false);             } :             function(target, eventType, handler) { //IE               target.detachEvent("on" + eventType, handler);             }
    复制代码

        这种方法,比前面比前面那种更加的“积极”,因为他是在函数调用之前就已经去检测浏览器类型了,调用的时候马上就可以正确的去绑定事件。

    PS:
    参考资料:Nicbolas C.Zakas 《High Performance JavaScript》;chapter 8 ;Don’t Repeat Work
    该书目前好像只有英文版而还没有中文版的。如果有需要的可以Google一下,下载个电子版的来看一下
  • 相关阅读:
    Cannot get a NUMERIC value from a STRING cell? 已解决
    Android Studio快捷键大全
    mysql索引
    eclipse中出现错误 Syntax error, insert "}" to complete Block
    function
    IGS OPC UA 配置
    IFIX 5.9 历史数据 曲线 (非SQL模式)
    IFIX 5.9 报警存sql
    IFIX 数据源 节点 标签 域名
    IFIX 目录结构
  • 原文地址:https://www.cnblogs.com/zhangchuanfeng/p/5827260.html
Copyright © 2020-2023  润新知