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一下,下载个电子版的来看一下
 
 
 

JavaScript跨浏览器绑定事件函数的优化的更多相关文章

  1. Javascript跨浏览器的事件对象

    一.跨浏览器的事件对象 var EventUtil = { ///添加事件 addHandler: function (element, type, handler) { if (element.ad ...

  2. js实现一些跨浏览器的事件方法

    用JavaScript实现事件的绑定,移除,以及一些常用的事件属性的获取,时常要考虑到在不同浏览器下的兼容性,下面给出了一个跨浏览器的事件对象: var EventUtil = { on: funct ...

  3. 跨浏览器的事件对象-------EventUtil 中的方法及用法

    什么是EventUti----封装好的事件对象 在JavaScript中,DOM0级.DOM2级与旧版本IE(8-)为对象添加事件的方法不同 为了以跨浏览器的方式处理事件,需要编写一段“通用代码”,即 ...

  4. EventUtil——跨浏览器的事件对象

    . 首页 博客园 联系我 前言:什么是EventUtil?. EventUtil对象全见. addHandler方法. removeHandler方法. event对象与getEvent方法. tar ...

  5. js事件对象--DOM中的事件对象/IE中的事件对象/跨浏览器的事件对象

    事件对象    在触发DOM上的某个事件时,会产生一个事件对象event,这个对象中包含着所有与事件有关的信息.包括导致事件的元素.事件的类型,以及其他与特定事件相关的信息.例如,鼠标操作导致的事件对 ...

  6. JavaScript三种绑定事件的方式

    JavaScript三种绑定事件的方式: 1. <div id="btn" onclick="clickone()"></div> // ...

  7. js 跨浏览器实现事件

    我们知道不同的浏览器实现事件是不同的,就比如说我们常见的有三种方法: 1,dom0处理事件的方法,以前的js处理事件都是这样写的. (function () { var p=document.getE ...

  8. js跨浏览器的事件处理函数

    /* 跨浏览器的事件处理函数 */ var EventUtil = { addHandler : function(element,type,handler){ if(element.addEvent ...

  9. 封装常用的Javascript跨浏览器方法

    var EventUntil={ // 跨浏览器的添加事件方法 addHandler:function(element,type,handler){ if(element.addEventListen ...

随机推荐

  1. VCL界面控件DevExpress VCL Controls发布v18.2.4|附下载

    DevExpress VCL Controls是 Devexpress公司旗下最老牌的用户界面套包.所包含的控件有:数据录入,图表,数据分析,导航,布局,网格,日程管理,样式,打印和工作流等,让您快速 ...

  2. 特殊权限stick_bit

    stick_bit 防删除位:文件是否可以被某用户删除,主要取决于该文件所在的目录是否对该用户具有写权限.如果没有写权限,则这个目录下的所有文件都不能删除,同时也不能添加新的文件.如果希望用户能够添加 ...

  3. dubbo的几种配置方式(转)

    昨天刚接触公司dubbo,发现公司中项目里面的spring-dubbo-privider的dubbo中<dubbo:application name=""/>和< ...

  4. 再谈kbmMW垃圾回收

    很早就写了关于kbmMW Server如何实现的垃圾回收,但最近一段时间还是为此遇到问题,实现的Server不能稳定运行,发生问题后不响应客户端的查询请求,在客户端得到服务端返回地址错误信息,只能重启 ...

  5. laravel 添加验证码

    1.  安装依赖  composer require gregwar/captcha 2.使用 use Gregwar\Captcha\CaptchaBuilder; use DB; use Requ ...

  6. jQuery的位置信息

    <head> <meta charset="UTF-8"> <title>jquery的位置信息</title> <style ...

  7. [LeetCode&Python] Problem 520. Detect Capital

    Given a word, you need to judge whether the usage of capitals in it is right or not. We define the u ...

  8. 修改JAVA代码,需要重启Tomcat的原因

    准确的说只有修改方法中的内容才不需要重启,因为tomcat中对于方法的调用是动态的,调用方法的时候,方法的内容才会被加载 新增成员变量,方法,或修改静态方法和静态变量.创建新的类 这些都是需要重启的, ...

  9. ZOJ - 4082:Little Sub and his Geometry Problem (双指针)

    Little Sub loves math very much, and has just come up with an interesting problem when he is working ...

  10. 微信导出群记录V3.0

    一.序 导出东北师范大学2017级软件工程微信群的聊天记录,形式不限,但需要包含文字.图片和链接,不允许截图. 聊天记录的时间段为2017年11月3日12:00起至2018年1月3日12:00. 二. ...