在触发DOM上的某个事件时,会产生一个时间对象event,该对象包含着所有与事件有关的信息。
所有的浏览器都支持event对象,但支持的方式不同。
一、DOM中的事件对象
兼容DOM的浏览器会将一个event对象传到事件处理程序中,而无论指定事件处理程序使用的是什么方法。
var btn = doucument.getElementById('myBtn');
btn.onclick = function(event){
alert(event.type);//'click'
}
btn.addEventListener('click',function(){
alert(event.type);//'click'
},false);
<input type="button" value="Click Me" onclick="alert(event.type)"/>
event对象的属性/方法
- bubbles Boolean 只读 表明事件是否冒泡
- cancelable Boolean 只读 表明是否可以取消事件的默认行为
- currentTarget Element 只读 其事件处理程序当前正在处理事件的那个元素
- defaultPrevented Boolean 只读
为true表示已经调用了preventDefault()(DOM3级事件中新增) - detail Integer 只读 与事件相关的细节信息
- eventPhase Integer 只读 调用事件处理程序的阶段:1表示捕获阶段,2表示“处于目标”,3表示冒泡阶段
- preventDefault() Function 只读 取消事件的默认行为。如果cancelable是true,则可以使用这个方法
- stopImmediatePropagation() Function 只读
取消事件的进一步捕获或冒泡,同时阻止任何事件处理程序被调用(DOM3级事件中新增) - stopPropagation() Function 只读
取消事件的进一步捕获或冒泡。如果bubbles为true,则可以使用这个方法 - target Element 只读 事件的目标
- trusted Boolean 只读
为true表示事件是浏览器生成的。为false表示事件是由开发人员通过JavaScript创建的(DOM3级事件中新增) - type String 只读 被触发的事件的类型
- view AbstractView 只读 与事件关联的抽象视图。等同于发生事件的window对象
在事件处理程序内部,this始终等于currentTarget的值,而target则只包含事件的实际目标。
var btn = doucument.getElementById('myBtn');
btn.onclick = function(event){
alert(event.currentTarget===this);//true
alert(event.target===this);//true
}
但是,如果dom中存在层级关系时:
doucument.body.onclick = function(event){
alert(event.currentTarget===doucument.body);//true
alert(this===doucument.body);//true
alert(event.target===doucument.getElementById('myBtn'));
}
当单击这个例子中的按钮时,this和currentTarget都等于document.body,因为事件处理程序是注册到这个元素上的。然而,target元素却等于按钮元素,因为它是click事件真正的目标。由于按钮上并没有注册事件处理程序,结果click事件就冒泡到了document.body,在那里事件才得到了处理。
当需要通过一个事件处理程序处理多个事件时,可以通过event对象的type属性:
var btn = document.getElementById("myBtn");
var handler = function(event){
switch(event.type){
case "click":
alert("Clicked");
break;
case "mouseover":
event.target.style.backgroundColor = "red";
break;
case "mouseout":
event.target.style.backgroundColor = "";
break;
}
};
btn.onclick = handler;
btn.onmouseover = handler;
btn.onmouseout = handler;
要阻止特定事件的默认行为,可以使用preventDefault()方法。
例如:取消超点击链接的跳转操作。
var link = document.getElementById("myLink");
link.onclick = function(event){
event.preventDefault();
};
只有cancelable属性设置为true的事件,才可以使用preventDefault()来取消其默认行为。
stopPropagation()方法用于立即停止事件在DOM层次中的传播,即取消进一步的事件捕获或冒泡。
例如,直接添加到一个按钮的事件处理程序可以调用stopPropagation(),从而避免触发注册在document.body上面的事件处理程序,
var btn = document.getElementById("myBtn");
btn.onclick = function(event){
alert("Clicked");
event.stopPropagation(); //阻止事件冒泡,所以只会弹出当前的对话框。
};
document.body.onclick = function(event){
alert("Body clicked");
};
事件对象的eventPhase属性,可以用来确定事件当前正位于事件流的哪个阶段。
eventPhase=1,在捕获阶段调用的事件处理程序
eventPhase=2,事件处理程序处于目标对象上
eventPhase=3,在冒泡阶段调用的事件处理程序
尽管“处于目标”发生在冒泡阶段,但eventPhase仍然一直等于2
var btn = document.getElementById("myBtn");
btn.onclick = function(event){
alert(event.eventPhase); //2 ,当eventPhase等于2时,this、target和currentTarget始终都是相等的
};
document.body.addEventListener("click", function(event){
alert(event.eventPhase); //1
}, true);
document.body.onclick = function(event){
alert(event.eventPhase); //3
};
只有在事件处理程序执行期间,event对象才会存在;一旦事件处理程序执行完成,event对象就会被销毁。
二、IE中的事件对象
DOM中的事件对象是传递到事件处理程序中的,所以在事件处理程序中直接通过event对象就可以访问。
而IE中的事件处理的访问形式,取决于添加事件处理程序的方法。
1.当使用DOM0级方法添加事件处理程序时,event对象作为window对象的一个属性存在
var btn = document.getElementById('myBtn');
btn.onclick = function(){
var event = window.event;
alert(event.type);//'click'
}
2.当使用attachEvent方法添加事件处理程序,会有一个event对象作为参数被传入事件处理程序的函数中。
var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function(event){
alert(event.type); //"click"
});
在像这样使用attachEvent()的情况下,也可以通过window对象来访问event对象,就像使用DOM0级方法时一样。不过为方便起见,同一个对象也会作为参数传递。
3.通过HTML特性指定事件处理程序
与访问DOM的event对象方式一样。
<input type="button" value="Click Me" onclick="alert(event.type)">
IE中事件对象的属性/方法:
- cancelBubble Boolean 读/写
默认值为false,但将其设置为true就可以取消事件冒泡(与DOM中的stopPropagation()方法的作用相同) - returnValue Boolean 读/写
默认值为true,但将其设置为false就可以取消事件的默认行为(与DOM中的preventDefault()方法的作用相同) - srcElement Element 只读 事件的目标(与DOM中的target属性相同)
- type String 只读 被触发的事件的类型
因为事件处理程序的作用域是根据指定它的方式来确定的,所以不能认为this会始终等于事件目标。故而,最好还是使用event.srcElement比较保险。
var btn = document.getElementById("myBtn");
btn.onclick = function(){ //DOM0级方法指定事件处理程序
alert(window.event.srcElement === this); //true
};
btn.attachEvent("onclick", function(event){
alert(event.srcElement === this); //false
});
returnValue属性相当于DOM中的preventDefault()方法,它们的作用都是取消给定事件的默认行为。只要将returnValue设置为false,就可以阻止默认行为。
var link = document.getElementById("myLink");
link.onclick = function(){
window.event.returnValue = false; //与DOM不同的是,在此没有办法确定事件是否能被取消。
};
cancelBubble属性与DOM中的stopPropagation()方法作用相同,都是用来停止事件冒泡的。由于IE不支持事件捕获,因而只能取消事件冒泡;但stopPropagatioin()可以同时取消事件捕获和冒泡。
var btn = document.getElementById("myBtn");
btn.onclick = function(){
alert("Clicked");
window.event.cancelBubble = true;
};
document.body.onclick = function(){
alert("Body clicked"); //被阻止弹出
};
三、跨浏览器的事件对象
虽然DOM和IE中的event对象不同,但基于它们之间的相似性依旧可以拿出跨浏览器的方案来。
我们在前面的EventUtil对象上加以改造。
var EventUtil = {
addHandler: function(element, type, handler){
//省略的代码
},
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;
}
},
removeHandler: function(element, type, handler){
//省略的代码
},
stopPropagation: function(event){ //由于IE不支持事件捕获,因此这个方法在跨浏览器的情况下,也只能用来阻止事件冒泡。
if (event.stopPropagation){
event.stopPropagation();
} else {
event.cancelBubble = true;
}
}
};
在使用这个方法时,必须假设有一个事件对象传入到事件处理程序中,而且要把该变量传给这个方法
btn.onclick = function(event){
event = EventUtil.getEvent(event);
};