1.事件流
事件流描述的是页面中元素接收事件的顺序。比如你单击了某个按钮,他们都认为单击事件不仅仅发生在按钮上,换句话说,在单击按钮的同时,你也单击了按钮的容器元素,甚至还单击了整个页面。那么你到底是先单击的按钮还是先单击的整个页面呢?
IE的事件流叫做事件冒泡,即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)。事件冒泡图:
Netspace团队提出的事件流叫做事件捕获,事件捕获的思想是不太具体的节点应该更早接收到事件,而最具体的节点应该最后接收到事件,事件捕获的用意在于在事件到达预定目标之前捕获它。事件捕获图:
“DOM2级事件”规定的事件流包括三个阶段:事件捕获阶段,处于目标阶段和事件冒泡阶段。在DOM事件流中,实际的目标(<div>元素)在捕获阶段不会接收到事件。这意味着在捕获阶段,事件从document到<html>再到<body>后就停止了。下一个阶段是“处于目标阶段”,于是事件在<div>上发生,并在事件处理中被看成是冒泡阶段的一部分。然后,冒泡阶段发生,事件又传播回文档。DOM事件流,如图:
由于老版本浏览器不支持事件捕获,所以很少有人使用事件捕获,大家可以放心使用事件冒泡,有特殊需求时再使用事件捕获。
2.DOM中的事件对象
在触发DOM上的某个事件时,会产生一个事件对象event,这个对象中包含着所以与事件有关的信息。包括导致事件的元素,事件的类型以及其他与特定事件相关的信息。兼容DOM的浏览器会将一个event对象传入到事件处理程序中。无论事件处理程序时使用什么方法(DOM0级或DOM2级),都会传入event对象。event对象包含于创建它的特定事件有关的方法和属性,触发的事件类型不一样,可以用的属性和方法也不一样。但是,所有事件中的event对象都有如下表所示的共同属性和方法:
属性/方法 | 类 型 | 读/写 | 说明 |
bubbles | Boolean | 只读 | 表示事件是否冒泡 |
cancelable | Boolean | 只读 | 表示是否可以取消事件的默认行为 |
currentTarget | Element | 只读 | 指其事件处理程序当前正在处理事件的那个元素 |
defaultPrevented | Boolean | 只读 | 为true表示已经调用了preventDefault()DOM3级事件中新增的方法 |
detail | Integer | 只读 | 与事件相关的细节信息 |
eventPhase | Integer | 只读 | 调用事件处理程序的阶段:1,表示捕获阶段 2.表示处于目标阶段 3.表示冒泡阶段 |
preventDefault() | Function | 只读 | 取消事件的默认行为,如果cancelabel是true,就可以使用这个方法 |
stopImmediatePropagation() | Function | 只读 | 取消事件的进一步捕获或冒泡,同时阻止任何事件处理程序被调用 |
stopPropagation() | Function | 只读 | 取消事件的进一步捕获或冒泡,如果bubbles为true,则可以使用这个方法 |
target | Element | 只读 | 事件的目标 |
trusted | Boolean | 只读 | 为true表示事件是浏览器生成的,为false表示事件是由开发人员通过JavaScript创建的 |
type | String | 只读 | 被触发的事件的类型 |
view | AbstractView | 只读 | 与事件关联的抽象视图 |
注意点:1.事件处理程序内部,对象this始终等于currentTarget的值,而target则只包含事件的实际目标,如果直接将事件处理程序指定给了目标元素,则this,currentTarget和target包含相同的值。
2.只有在事件处理程序执行期间,event对象才存在,一旦事件处理程序执行完成,event对象就会被销毁。
使用type属性处理多个事件 参考案例代码:
//使用type属性,处理多个事件
var btn =document.getElementById('myBtn');
var handler=function(event){
switch(event.type){
case 'click':
alert('1');
break;
case 'mouseover':
alert('2');
break;
case 'mouseout':
alert('3');
break;
}
};
btn.onclick=handler;
btn.onmouseover=handler;
btn.onmouseout=handler;
3.IE中的事件对象
访问IE中的event对象与访问DOM中的event对象不同,取决于指定事件处理程序的方法。
如果使用DOM0级方法添加事件处理程序,那么event对象作为window对象的一个属性存在,如下面的例子:
var btn =document.getElementById('myBtn');
btn.onclick=function(){
var event=window.event;
alert(event.type); //click
}
如果事件处理程序是使用attachEvent()添加的,那么就会有一个event对象作为参数被传入事件处理程序函数中,如下例子所示:
var btn =document.getElementById('myBtn');
btn.attachEvent('onclick',function(){
alert(event.type); //click
})
IE中的事件对象包含的属性和方法:
属性/方法 | 类 型 | 读/写 | 说 明 |
cancelBubble | Boolean | 读/写 | 默认为false,把它设为true时就可以取消事件,冒泡,与DOM中的stopPropagation()方法的作用相同。 |
returnValue | Boolean | 读/写 | 默认值为true,把它设为false就可以取消事件的默认行为。与DOM中的preventDefault()方法作用相同。 |
SRCElement | Element | 只读 | 事件的目标,与DOM中的target属性相同 |
type | String | 只读 | 被触发事件的类型 |
4.跨浏览器的事件对象
基于DOM的事件对象和IE的事件对象具有相似性,我们可以编写一套跨浏览器使用的事件对象的方法:
//可用于跨浏览器添加事件处理程序和事件对象
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;
}
},
//获取event对象的引用
getEvent:function(evnet){
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;
}
}
}
使用方法如下面的演示例子:
var btn=document.getElementById('myBtn');
btn.onclick=function(event){
//用于获取事件对象
event=EventUtil.getEvent(event);
//获取目标元素
var target=EventUtil.getTarget(event);
}