JavaScript跨浏览器事件处理方式

65 阅读4分钟

事件流是描述从页面中接收数据的顺序,但是IE和Netspace开发团队提出了差不多完全相反的事件流概念。IE事件流是事件冒泡,而Netspace Comminicator 的事件流是事件捕获。

一、DOM事件流

“DOM2级事件”规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段,在DOM事件流中目标元素在捕获阶段不会接受到数据,而是作为事件冒泡阶段的一部分。

二、事件处理程序

事件处理程序就是相应某个事件的函数,为事件指定处理程序的方式有以下几种:

1、HTML事件处理程序

在元素标签内绑定:

<script>
   function showMessage(){
    console.log('hello world')  
}
</script>
<input type = "button" onclick = "showMessage()" />

2、DOM0级事件处理程序

这是通过JavaScript指定事件处理的传统方式,讲一个函数赋值给一个事件处理程序属性。这种方式是在第四代Web浏览器中出现的,至今依然被所有浏览器支持。原因一是简单,二是具有跨浏览器优势;

var btn = document.getElementById("myButton");
btn.onclick = function(){
  console.log('hello world')
}

3、DOM2级事件处理程序

DOM2级事件处理定义了两个方法:addEventListener() 和 removeEventListener()用于处理事件程序和删除事件处理程序操作,相信大家对这两个方法已经不陌生了,在此不做详细介绍。

在DOM事件处理中,this指向当前元素!!!!!

目前支持DOM2级事件处理程序的浏览器:IE9、Firefox、Chrome、Opera

4、IE事件处理程序

IE实现了与DOM中类似的两个方法:attachEvent() 和 detachEvent(),由于IE8以前的版本只支持事件冒泡,所以通过上述添加的事件都会被添加到冒泡阶段。

IE事件处理中,this指向window!!!!!在编写跨浏览器代码时一定注意!!!!

三、事件对象

1、DOM中的事件对象

在触发DOM上的某个事件时,会产生一个事件对象event,包含着与事件有关的信息。

兼容DOM的浏览器会将一个event对象传入到事件处理程序中,无论是DOM0级还是DOM2级。

只有在事件处理程序执行期间,event对象才存在,一旦事件处理程序完成,event就会被销毁。

在事件处理程序内部,对象this始终等于currentTarget的值,而target则只是包含事件的实际目标。

event 包含的属性和方法:

属性/方法类型读/写说明
bubblesBoolean只读   表明事件是否冒泡
stopPropagation()Function只读取消事件的进一步捕获或冒泡。如果bubbles为true,则可以使用这个方法
stopImmediatePropagation() Function只读取消事件的进一步捕获或冒泡 ,同时阻止任何事件处理程序被调用(DOM3级事件中新增)
cancelableBoolean只读表明是否可以取消事件的默认行为
preventDefault()Function只读取消事件的默认行为。如果cancelable是true,则可以使用这个方法
defaultPreventedBoolean只读为true表示已经调用了preventDefault()(DOM3级事件中新增)
currentTargetElement只读其事件处理程序当前正在处理事件的那个元素(currentTarget始终===this,即处理事件的元素)
targetElement只读直接事件目标,真正触发事件的目标
detailInteger 只读与事件相关的细节信息
eventPhaseInteger只读调用事件处理程序的阶段:1表示捕获阶段,2表示处于目标阶段,3表示冒泡阶段
trustedBoolean只读为true表示事件是由浏览器生成的。为false表示事件是由开发人员通过JavaScript创建的(DOM3级事件中新增)
typeString只读被触发的事件的类型
viewAbstractView只读与事件关联的抽象视图。等同于发生事件的window对象

2、IE中事件对象

与DOM中的事件对象不同,要访问IE中的event对象有几种不同的方式,取决于事件处理程序的方法:

  • 用DOM0级方法添加事件处理程序时,event对象是作为window的一个属性存在,所以必须通过window.event获取
  • 如果是通过attacheEvent()添加的,那么event会作为参数传入(同DOM事件对象)

IE的event对象属性:

属性/方法类型读/写说明
cancelBubbleBoolean读/写默认为false,但将其设置为true就可以取消事件冒泡(与DOM中stopPropagation()方法的作用相同
returnValueBoolean读/写默认为true,但将其设置为false就可以取消事件的默认行为(与DOM中的preventDefault()方法的作用相同
srcElementElement只读事件的目标(与DOM中的target属性相同
typeString只读被触发的事件的类型

四、跨浏览器事件解决方案

综上所述,编写跨浏览器的事件处理程序:

var EventUtil = {
  addHandler: function(element, type, handler){
    if(element.addEvenListener){
      element.addEventListener(type, handler, false);
    }else if(element.attachEvent){
      element.attacheEvent("on" + type, handler);
    }else{
      element["on" + type] = handler;
    }
 },
 removeHandler:function(){
  if(element.addEvenListener){
      element.removeEventListener(type, handler, false);
    }else if(element.attachEvent){
      element.detacheEvent("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
   }
 }
}