在触发DOM中的某个事件的时候,会产生一个事件对象event
,这个对象包含着所有与事件相关的信息。这些信息包括发生事件的元素,事件的类型和其它一些特定的相关信息。所有的浏览器都支持event
事件对象,但是各个浏览器的支持方式各不相同。
DOM中的事件对象
所有兼容DOM的浏览器都会将一个event
对象传入到事件处理程序中。不管是DOM0级事件处理方法还是DOM2级事件处理方法,都会传入event
对象。例如
var btn = document.getElementById("btn"); /* DOM0级方法 */ btn.onclick = function(event){ console.info(event.type); //输出:“click” } /* DOM2级方法 */ btn.addEventListener("click",function(event){ console.info(event.type); //输出:“click” },false);
event
对象包含与创建它的特定事件有关的属性和方法。触发事件的类型不一样,可用的属性和方法也不一样。下表中列出了通用的属性和方法。
属性/方法 | 类型 | 读 / 写 | 描述 |
bubbles | Boolean | 只读 | 事件是否冒泡 |
cancelable | Boolean | 只读 | 是否可以取消事件的默认行为 |
curentTarget | Element | 只读 | 当前正在处理事件的事件处理程序的元素 |
detail | Integer | 只读 | 与事件相关的细节信息 |
eventPhase | Integer | 只读 | 调用事件处理程序的阶段:1表示捕获阶段,2表示“处于目标”阶段,3表示冒泡阶段 |
preventDefault() | Function | 只读 | 取消事件的默认行为 |
stopPropagation() | Function | 只读 | 取消事件的进一步捕获或冒泡。如果bubbles 为true 则可以使用该方法 |
target | Element | 只读 | 事件的目标 |
type | String | 只读 | 被触发事件的类型 |
view | AbstractView | 只读 | 与事件关联的抽象视图。等同于发生事件的window对象 |
在事件处理程序的内部,对象this
始终等于curentTarget
的值,target
包含的是事件的实际目标。
要阻止事件的默认行为,可以使用preventDefault()
方法。例如,超链接的默认行为是在被单击的时候导航到某个URL上。如果想阻止超链接的默认行为,可以通过在超链接的onclick
事件处理程序中取消它,代码如下:
var link = document.getElementById("myLink"); link.onclick = function(event){ event.preventDefault(); }
另外,只有在cancelable
属性被设置为true
的时候,才可以使用preventDefault()
方法来取消默认行为。
stopPropagation()
方法用于立刻停止事件在DOM中的传播,也就是说可以取消事件捕获或事件冒泡。例如下面的例子:
<html lang="zh" id="html" class="demo"> <head> <meta charset="UTF-8"> <title>事件冒泡</title> </head> <body id="body" class="demo"> <div id="parent" class="demo"> <button id="child" class="demo">点击一下</button> </div> <script type="text/javascript"> window.onload = function(){ var elements = document.querySelectorAll(".demo"); //alert(elements.length); for(var i = 0 ; i < elements.length; i++){ elements[i].onclick = function(event){ var element = elements[i]; //获取事件 event = event?event:window.event; //获取事件发生的目标 target = event.target?event.target:event.srcElement; console.info("事件源:"+target.id+" , "+target.tagName+", 事件对象:"+this.id); } } } </script> </body> </html>
上面的代码会产生事件冒泡,从控制台中可以看到事件冒泡的结果。如果要取消事件冒泡,只需要添加event.stopPropagation();
即可。
<html lang="zh" id="html" class="demo"> <head> <meta charset="UTF-8"> <title>事件冒泡</title> </head> <body id="body" class="demo"> <div id="parent" class="demo"> <button id="child" class="demo">点击一下</button> </div> <script type="text/javascript"> window.onload = function(){ var elements = document.querySelectorAll(".demo"); //alert(elements.length); for(var i = 0 ; i < elements.length; i++){ elements[i].onclick = function(event){ var element = elements[i]; //获取事件 event = event?event:window.event; //获取事件发生的目标 target = event.target?event.target:event.srcElement; console.info("事件源:"+target.id+" , "+target.tagName+", 事件对象:"+this.id); //取消事件冒泡 event.stopPropagation(); } } } </script> </body> </html>
可以看到,此时,在控制台中显示的事件对象只有按钮对象。
事件对象的eventPhase
属性可以知道当前正处于事件流的哪一个阶段。如果eventPhase
属性的值等于1,那么事件流处于捕获阶段;如果eventPhase
属性的值等于2,那么事件处于目标对象上;如果eventPhase
属性的值等于3,那么事件处于冒泡阶段。
IE中的事件对象
与访问DOM中的event
对象不同,要访问IE中的event
对象有几种不同的方式,取决于指定事件处理程序的方法。在使用DOM0级方法添加事件处理程序时,event
对象作为window
对象的一个属性存在。例如下面的例子:
var btn = document.getElementById("btn"); btn.onclick = function(){ var event = window.event; console.info(event.type); //输出"click" }
上面的例子通过window.event
获取了event
对象,并获取了被触发事件的类型。
如果事件处理程序使用的是attachEvent()
,那么会有一个event
对象作为参数被传入到事件处理程序函数中,例如:
var btn = document.getElementById("btn"); btn.attachEvent("onclick",function(event){ console.info(event.type); //输出"click" });
如果是使用HTML属性来指定事件处理程序,那么还可以通过一个event
变量来访问event
对象,例如:
<input type="button" value="点击" onclick="alert(event.type)"/>
IE中的event
对象也包含与创建它的事件相关的一些属性和方法。其中很多属性和方法都有对应或相关的DOM属性和方法。下表中列出了所有事件对象都包含的属性和方法。
属性/方法 | 类型 | 读 / 写 | 描述 |
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("btn"); btn.onclick = function(){ console.info(window.event.srcElement === this); //输出true } btn.attachEvent("onclick",function(event){ console.info(event.srcElement === this); //输出false });
上面的代码中,第一个事件处理程序使用的是DOM0级事件处理程序,srcElement
属性等于this
。但是在第二个IE事件处理程序中,这两个值则是不同的。
returnValue
属性相当于DOM中的preventDefault()
方法,它的作用是取消事件的默认行为。要取消事件的默认行为,只需要将该属性的值设置为false
即可。例如:
var link = document.getElementById("myLink"); link.onclick = function(){ window.event.returnValue = false; }
上面的例子中,指定的超链接在点击之后不会被导航到指定的URL上。
最后,cancelBubble
属性与DOM中的stopPropagation()
方法相同,用于停止事件冒泡。由于IE不支持事件捕获,因此只能用它来阻止事件冒泡。stopPropagation()
方法可以同时取消事件冒泡和事件捕获。
跨浏览器事件对象
我们可以通过自定义函数来实现跨浏览器的事件对象。
首先是跨浏览器获取是事件对象的方法。该方法返回对event
对象的引用。
/* 跨浏览器获取event对象 */ function getEvent(event){ return event ? event : window.event; }
然后是跨浏览器获取事件的目标。
/* 跨浏览器获取事件的目标 */ function getTarget(event){ return event.target ? event.target : event.srcElement; }
接着是跨浏览器阻止事件默认行为的方法。
/* 跨浏览器阻止事件默认行为 */ function preventDefault(event){ if(event.preventDefault){ event.preventDefault(); }else{ event.returnValue = false; } }
最后是跨浏览器阻止事件冒泡的方法。
/* 跨浏览器阻止事件冒泡 */ function stopPropagation(event){ if(event.stopPropagation){ event.stopPropagation(); }else{ event.cancelBubble = true; } }