JavaScript 与 HTML 之间的交互是通过事件实现的。事件,就是文档或浏览器窗口中发生的一些 特定的交互瞬间。
13.1 事件流
事件流描述的是从页面中接收事件的顺序。
-
13.1.1 事件冒泡
IE 的事件流叫做事件冒泡(event bubbling),即事件开始时由最具体的元素(文档中嵌套层次最深 的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)。
<!DOCTYPE html>
<html>
<head>
<title>Event Bubbling Example</title>
</head>
<body>
<div id="myDiv">Click Me</div>
</body>
</html>
如果你单击了页面中的 <div> 元素,那么这个 click 事件会按照如下顺序传播:
(1) <div>
(2) <body>
(3) <html>
(4) document

-
13.1.2 事件捕获
事件捕获的用意在于在事件到达预定目标之前捕获它。
// 如果仍以前面的 HTML 页面作为演示事件捕获的例子,那么单击 <div>元素就会以下列顺序触发click事件。
(1) document
(2) <html>
(3) <body>
(4) <div>

-
13.1.3 DOM事件流
“DOM2级事件”规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。

13.2 事件处理程序
响应某个事件的函数就叫做事件处理程序
-
13.2.1 HTML事件处理程序
某个元素支持的每种事件,都可以使用一个与相应事件处理程序同名的 HTML 特性来指定。
<input type="button" value="Click Me" onclick="alert('Clicked')" /> -
13.2.2 DOM0 级事件处理程序
每个元素(包括 window 和 document )都有自己的事件处理程序属性,这些属性通常全部小写。
var btn = document.getElementById("myBtn"); btn.onclick = function(){ alert("Clicked"); }; -
13.2.3 DOM2 级事件处理程序
“DOM2级事件”定义了两个方法,用于处理指定和删除事件处理程序的操作:addEventListener()和removeEventListener() 。
var btn = document.getElementById("myBtn"); btn.addEventListener("click", function(){ alert("Hello world!"); }, false); btn.removeEventListener("click", function(){ alert("Hello world!"); }, false); -
13.2.4 IE事件处理程序
IE 实现了与 DOM 中类似的两个方法: attachEvent() 和 detachEvent() 。
var btn = document.getElementById("myBtn"); btn.attachEvent("onclick", function(){ alert("Clicked"); }); btn.detachEvent("onclick", function(){ alert("Clicked"); }); -
13.2.5 跨浏览器的事件处理程序
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;
}
}
};
13.3 事件对象
在触发 DOM 上的某个事件时,会产生一个事件对象 event,这个对象中包含着所有与事件有关的信息。
-
13.3.1 DOM中的事件对象
兼容 DOM 的浏览器会将一个 event 对象传入到事件处理程序中。
var btn = document.getElementById("myBtn"); btn.onclick = function(event){ alert(event.type); //"click" }; btn.addEventListener("click", function(event){ alert(event.type); //"click" }, false);

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

var btn = document.getElementById("myBtn");
btn.onclick = function(){
alert("Clicked");
window.event.cancelBubble = true;
};
document.body.onclick = function(){
alert("Body clicked");
};
- 13.3.3 跨浏览器的事件对象
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){
if (event.stopPropagation){
event.stopPropagation();
} else {
event.cancelBubble = true;
}
}
};
13.4 事件类型
DOM3级事件”规定了以下几类事件。

13.5 内存和性能
-
13.5.1 事件委托
事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
<ul id="myLinks"> <li id="goSomewhere">Go somewhere</li> <li id="doSomething">Do something</li> <li id="sayHi">Say hi</li> </ul> var list = document.getElementById("myLinks"); EventUtil.addHandler(list, "click", function(event){ event = EventUtil.getEvent(event); var target = EventUtil.getTarget(event); switch(target.id){ case "doSomething": document.title = "I changed the document's title"; break; case "goSomewhere": location.href = "http://www.wrox.com"; break; case "sayHi": alert("hi"); break; } });
13.7 小结
事件是将 JavaScript 与网页联系在一起的主要方式。“DOM3 级事件”规范和 HTML5 定义了常见的 大多数事件。即使有规范定义了基本事件,但很多浏览器仍然在规范之外实现了自己的专有事件,从而 为开发人员提供更多掌握用户交互的手段。有些专有事件与特定设备关联,例如移动 Safari 中的 orientationchange 事件就是特定关联 iOS 设备的。
在使用事件时,需要考虑如下一些内存与性能方面的问题。
有必要限制一个页面中事件处理程序的数量,数量太多会导致占用大量内存,而且也会让用户 感觉页面反应不够灵敏。
建立在事件冒泡机制之上的事件委托技术,可以有效地减少事件处理程序的数量。
建议在浏览器卸载页面之前移除页面中的所有事件处理程序。
可以使用 JavaScript 在浏览器中模拟事件。“DOM2 级事件”和“DOM3 级事件”规范规定了模拟事 件的方法,为模拟各种有定义的事件提供了方便。此外,通过组合使用一些技术,还可以在某种程度上 模拟键盘事件。IE8及之前版本同样支持事件模拟,只不过模拟的过程有些差异。
事件是 JavaScript中最重要的主题之一,深入理解事件的工作机制以及它们对性能的影响至关重要。