第十三章 - 事件
本章内容
- 理解事件流
- 使用事件处理程序
- 不同的事件类型
JS与HTML之间的交互是通过事件实现的。可以使用侦听器(或处理程序)来预订事件,以便事件发生时执行相应的代码。
13.1 事件流
事件流描述的是从页面中接收事件的顺序。IE 的事件流是事件冒泡流,而 Netscape Communicator 的事件流是事件捕获流。
13.1.1 事件冒泡
IE 的事件流叫做事件冒泡(event bubbling),即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)。
13.1.2 事件捕获(很少用)
事件捕获的思想是不太具体的节点应该更早接收到事件,而最具体的节点应该最后接收到事件。
13.1.3 DOM事件流
在 DOM 事件流中,实际的目标(元素)在捕获阶段不会接收到事件。这意味着在捕获阶段,事件从 document 到再到后就停止了。下一个阶段是“处于目标”阶段,于是事件在上发生,并在事件处理(后面将会讨论这个概念)中被看成冒泡阶段的一部分。然后,冒泡阶段发生,事件又传播回文档。
13.2 事件处理程序
事件就是用户或浏览器自身执行的某种动作。诸如 click、load 和 mouseover,都是事件的名字。而响应某个事件的函数就叫做事件处理程序(或事件侦听器)。
13.2.1 HTML事件处理程序
13.2.2 DOM0 级事件处理程序
通过 JavaScript 指定事件处理程序的传统方式,就是将一个函数赋值给一个事件处理程序属性。 使用 DOM0 级方法指定的事件处理程序被认为是元素的方法。因此,这时候的事件处理程序是在元素的作用域中运行;换句话说,程序中的 this 引用当前元素。
var btn = document.getElementById("myBtn");
btn.onclick = function(){
alert(this.id); //"myBtn"
};
13.2.3 DOM2 级事件处理程序
DOM2 级事件”定义了两个方法,用于处理指定和删除事件处理程序的操作:**addEventListener()**和 removeEventListener()。
var btn = document.getElementById("myBtn");
btn.addEventListener("click", function(){
alert(this.id);
}, false);
使用 DOM2 级方法添加事件处理程序的主要好处是可以添加多个事件处理程序,处理程序会按照添加它们的顺序触发。 通过 addEventListener()添加的事件处理程序只能使用 removeEventListener()来移除;移除时传入的参数与添加处理程序时使用的参数相同。这也意味着通过 addEventListener()添加的匿名函数将无法移除。
13.2.4 IE事件处理程序
IE 实现了与 DOM 中类似的两个方法:**attachEvent()**和 detachEvent()。通过attachEvent()添加的事件处理程序都会被添加到冒泡阶段。 要使用 attachEvent()为按钮添加一个事件处理程序,可以使用以下代码。
var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function(){
alert("Clicked");
});
在 IE 中使用 attachEvent()与使用 DOM0 级方法的主要区别在于事件处理程序的作用域。在使用 DOM0 级方法的情况下,事件处理程序会在其所属元素的作用域内运行;在使用 attachEvent()方法的情况下,事件处理程序会在全局作用域中运行,因此 this 等于 window。 使用 attachEvent()添加的事件可以通过 detachEvent()来移除,条件是必须提供相同的参数。 比较表格如下:
DOM0 级事件处理程序 | DOM2 级事件处理程序 | IE事件处理程序 | |
---|---|---|---|
添加事件处理程序 | 只能添加一个同一事件;事件处理程序在元素的作用域内运行 | 可添加多个;可设置在捕获阶段还是冒泡阶段 | IE的;可添加多个;在全局作用域内;冒泡阶段 |
13.2.5 跨浏览器的事件处理程序
要保证处理事件的代码能在大多数浏览器下一致地运行,只需关注冒泡阶段。 第一个要创建的方法是 addHandler(),它的职责是视情况分别使用 DOM0 级方法、DOM2 级方法或 IE 方法来添加事件。这个方法属于一个名叫 EventUtil 的对象。 addHandler()方法接受 3 个参数:要操作的元素、事件名称和事件处理程序函数。
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,这个对象中包含着所有与事件有关的信息。 在需要通过一个函数处理多个事件时,可以使用 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();
};
stopPropagation()方法用于立即停止事件在 DOM 层次中的传播,即取消进一步的事件捕获或冒泡。
var btn = document.getElementById("myBtn");
btn.onclick = function(event){
alert("Clicked");
event.stopPropagation();
};
document.body.onclick = function(event){
alert("Body clicked");
};
事件对象的 eventPhase 属性,可以用来确定事件当前正位于事件流的哪个阶段。捕获阶段1,目标对象2,冒泡阶段3。
13.3.2 IE中的事件对象
略。
13.3.3 跨浏览器的事件对象
略。
13.4 事件类型
“DOM3级事件”规定了以下几类事件。
- UI(User Interface,用户界面)事件,当用户与页面上的元素交互时触发;
- 焦点事件,当元素获得或失去焦点时触发;
- 鼠标事件,当用户通过鼠标在页面上执行操作时触发;
- 滚轮事件,当使用鼠标滚轮(或类似设备)时触发;
- 文本事件,当在文档中输入文本时触发;
- 键盘事件,当用户通过键盘在页面上执行操作时触发;
- 合成事件,当为 IME(Input Method Editor,输入法编辑器)输入字符时触发;
- 变动(mutation)事件,当底层 DOM 结构发生变化时触发。
略。
13.5 内存和性能
在 JavaScript 中,添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能。