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. dubbo的几种配置方式(转)

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

  2. Gym - 100971J (思维+简单bfs)

    题目链接:http://codeforces.com/gym/100971/problem/J J. Robots at Warehouse time limit per test 2.0 s mem ...

  3. 手机号的 AES/CBC/PKCS7Padding 加解密

    前言:接口中上次的手机号码和密码是传入的加密的,模拟自动化的时候也需要先对数据进行加密 1.各种语言实现 网上已经各种语言实现好的AES加密,可以点击查看:http://outofmemory.cn/ ...

  4. VC下CString类型与int 、float等数据类型的相互转换

    一.常用转换 1. CString --> int转换 CString str("1234");    int i= _ttoi(str); 2. CString --> ...

  5. python-django的生命周期

    wsgi,请求封装后交给web框架(flask,django) 中间件,对请求进行校验或在请求对象中添加其他相关数据,列如(scrf[跨域],request,session) 路由匹配,根据浏览器发送 ...

  6. 分类算法的R语言实现案例

    最近在读<R语言与网站分析>,书中对分类.聚类算法的讲解通俗易懂,和数据挖掘理论一起看的话,有很好的参照效果. 然而,这么好的讲解,作者居然没提供对应的数据集.手痒之余,我自己动手整理了一 ...

  7. js编写轮播图,广告弹框

    1.轮播图 js编写轮播图,需要用到setInterval(计时器):先给一个div,里面放轮播图的图片,将轮播图的图片明明为相同样式的:如:banner1.jpg,banner2.jpg,banne ...

  8. puppet替换文件中的string

    文件 <VirtualHost :80> RewriteEngine On RewriteCond %{HTTPS} off RewriteRule (.) https://%{SERVE ...

  9. php-xdebug(安装)

    我虽然是前端人员,但是我也挺喜欢服务端语言的,我不是说完全不会服务端语言,主要是没有实践经验,实践经验不一样非要公司的项目,自己也可以去模仿一些项目,那也是实践的.所以就有了想法,自己写个项目,从后端 ...

  10. s21day03 python笔记

    s21day03 python笔记 一.昨日内容回顾及补充 回顾 补充 运算符补充 in 在里面 not in 不在里面 优先级补充(>优先于not) 二.整型(int) 数字表示 python ...