javascript中关于冒泡事件的常用方法

来源:互联网 发布:淘宝文具盒 编辑:程序博客网 时间:2024/06/11 18:01

在漫长的演变史,我们已经告别了内嵌式的事件处理方式(直接将事件处理器放在 HTML 元素之内来使用)。今天的事件,它已是DOM的重要组成部分,遗憾的是, IE继续保留它最早在IE4.0中实现的事件模型,以后的IE版本中也没有做太大的改变,这也就是说IE还是使用的是一种专有的事件模型(冒泡型),而其它的主流浏览器直到DOM 级别 3 规定定案后,才陆陆续续支持DOM标准的事件处理模型 — 捕获型与冒泡型。

历史原因是:W3C 规范 在DOM 级别 1中并没有定义任何的事件,直到发布于 2000 年 11 月 的DOM 级别 2 才定义了一小部分子集,DOM 级别 2中已经提供了提供了一种更详细的更细致的方式以控制 Web 页面中的事件,最后,完整的事件是在2004年 DOM 级别 3的规定中才最终定案。因为IE4是1995推出的并已实现了自己的事件模型(冒泡型),当时根本就没有DOM标准,不过在以后的DOM标准规范过程中已经把IE的事件模型吸收到了其中。

目前除IE浏览器外,其它主流的Firefox, Opera,
Safari都支持标准的DOM事件处理模型。IE仍然使用自己专有的事件模型,即冒泡型,它事件模型的一部份被DOM标准采用,这点对于开发者来说也是有好处的,只有使用
DOM标准,IE都共有的事件处理方式才能有效的跨浏览器。

IE低版本浏览器与标准W3C浏览器的区别

针对IE模型的事件写法,适用于IE6,7,8

IE的事件模型相比W3C的标准事件,主要有以下几点不同:

1.绑定事件的函数不同,IE中使用的是attachEvent(),detachEvent()

2.事件必须加上on

3.在IE 7,8中还有一个毛病就是先绑定的函数后执行,或者是随机执行

4.IE6 模型中,不支持捕捉模型,只支持冒泡模型。

5.绑定的事件中,this 的指向问题,w3c模型中,this指向对象本身,而IE模型中this指向的的是window

6.IE中不会自动传递event对象,而是使用的是window.event对象。

简单的解决方案:

function  addEvent(obj,type,event,model){

if(!(obj['__'+type])){

obj[('__'+type)]=[];

}

obj[('__'+type)].push(event);

if(!obj[('on'+type)]){

obj['on'+type]=function(){

for(var len=obj['__'+type].length,i=0;i<len;i++){

obj[('__'+type)][i].applay(obj);

}

}

}

}

跨浏览器的注册与移除元素事件监听器方案

我们现在已经知道,对于支持addEventListener方法的浏览器,只要需要事件监听器脚本就都需要调用addEventListener方法;而对于不支持该方法的IE浏览器,使用事件监听器时则需要调用attachEvent方法。要确保浏览器使用正确的方法其实并不困难,只需要通过一个if-else语句来检测当前浏览器中是否存在addEventListener方法或attachEvent方法即可。

这样的方式就可以实现一个跨浏览器的注册与移除元素事件监听器方案:

 var EventUtil = {
  //注册
  addHandler: function(element, type, handler){
    if (element.addEventListener){
      element.addEventListener(type, handler, false);
    } else if (element.attachEvent){
      element.attachEvent("on" + type, handler);
    } else {
      element["on" + type] = handler;
    }
  },
  //移除注册
  removeHandler: function(element, type, handler){
    if (element.removeEventListener){
            element.removeEventListener(type, handler, false);
    } else if (element.detachEvent){
            element.detachEvent("on" + type, handler);
    } else {
            element["on" + type] = null;
    }
  }             
 };

事件对象引用

为了更好的处理事件,你可以根据所发生的事件的特定属性来采取不同的操作。

如事件模型一样,IE 和其他浏览器处理方法不同:IE 使用一个叫做 event 的全局事件对象来处理对象(它可以在全局变量window.event中找到),而其它所有浏览器采用的 W3C 推荐的方式,则使用独立的包含事件对象的参数传递。

跨浏览器实现这样的功能时,最常见的问题就是获取事件本身的引用及获取该事件的目标元素的引用。

下面这段代码就为你解决了这个问题:



 var EventUtil ={
  getEvent: function(event){
    return event ? event : window.event;
  },
  getTarget: function(event){
    return event.target || event.srcElement;
  }
};

停止事件冒泡的处理方法

在IE下,通过设置event对象的cancelBubble为true即可。

因些,跨浏览器的停止事件传递的方法是:

function someHandle(event) {
  event = event || window.event;
  if(event.stopPropagation){
    event.stopPropagation();
  }else {
    event.cancelBubble = true;
  }
}

阻止事件的默认行为的处理方法

就像事件模型和事件对象差异一样,在IE和其它所有浏览器中阻止事件的默认行为的方法也不同。

在IE下,通过设置event对象的returnValue为false即可。

 function someHandle(event) {
  event = event || window.event;
  if(event.preventDefault){
    event.preventDefault();
  }else{
    event.returnValue = false;
  }
}

完整的事件处理兼容性函数:


var EventUtil = {
  addHandler: function(element, type, handler){
    if (element.addEventListener){
      element.addEventListener(type, handler, false);
    } else if (element.attachEvent){
      element.attachEvent("on" + type, handler);
    } else {
      element["on" + type] = handler;
    }
  },
  removeHandler: function(element, type, handler){
    if (element.removeEventListener){
      element.removeEventListener(type, handler, false);
    } else if (element.detachEvent){
      element.detachEvent("on" + type, handler);
    } else {
      element["on" + type] = null;
    }
  },
  getEvent: function(event){
    return event ? event : window.event;
  },
  getTarget: function(event){
    return event.target || event.srcElement;
  },
  preventDefault: function(event){
    if (event.preventDefault){
      event.preventDefault();
    } else {
      event.returnValue = false;
    }
  },
  stopPropagation: function(event){
    if (event.stopPropagation){
      event.stopPropagation();
    } else {
      event.cancelBubble = true;
    }
};

0 0
原创粉丝点击