addEventListener 用于注册事件处理程序,IE 中为 attachEvent,我们为什么讲 addEventListener 而不讲 attachEvent 呢?一来 attachEvent 比较简单,二来 addEventListener 才是 DOM 中的标准内容。
简介
addEventListener 为文档节点、document、window 或 XMLHttpRequest 注册事件处理程序,在以前我们一般是 <input type="button" οnclick="...",或 document.getElementById("testButton").onclick = FuncName, 而在 DOM 中,我们用 addEventListener(IE 中用 attachEvent)。
语法
- target 文档节点、document、window 或 XMLHttpRequest。
- type 字符串,事件名称,不含“on”,比如“click”、“mouseover”、“keydown”等。
- listener 实现了 EventListener 接口或者是 JavaScript 中的函数。
- useCapture 是否使用捕捉,看了后面的事件流一节后就明白了,一般用 false。
示例
//...
}
document.getElementById("testButton").addEventListener("click", Go, false);
或者 listener 直接就是函数
当一个事件发生时,分为三个阶段:
捕获阶段 从根节点开始顺序而下,检测每个节点是否注册了事件处理程序。如果注册了事件处理程序,并且 useCapture 为 true,则调用该事件处理程序。(IE 中无此阶段。)
目标阶段 触发在目标对象本身注册的事件处理程序,也称正常事件派发阶段。
冒泡阶段 从目标节点到根节点,检测每个节点是否注册了事件处理程序,如果注册了事件处理程序,并且 useCapture 为 false,则调用该事件处理程序。
举例
<div id="div2">
<div id="div3">
<div id="div4"></div>
</div>
</div>
</div>
如果在 div3 上点击鼠标,事件流是这样的:
捕获阶段 在 div1 处检测是否有 useCapture 为 true 的事件处理程序,若有,则执行该程序,然后再同样地处理 div2。
目标阶段 在 div3 处,发现 div3 就是鼠标点击的节点,所以这里为目标阶段,若有事件处理程序,则执行该程序,这里不论 useCapture 为 true 还是 false。
冒泡阶段 在 div2 处检测是否有 useCapture 为 false 的事件处理程序,若有,则执行该程序,然后再同样地处理 div1。
注意,上述捕获阶段和冒泡阶段中,实际上 div1 之上还应该有结点,比如有 body,但这里不讨论。
addEventListener-第三个参数useCapture
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>useCapture</title>
<style type="text/css">
#outDiv{ padding:10px; border:1px solid red; }
#middleDiv{ padding:10px; border:1px solid green; }
#inDiv{ padding:10px;border:1px solid blue;}
</style>
</head>
<body>
<div id="outDiv">
<div id="middleDiv">
<div id="inDiv">请在此点击鼠标。</div>
</div>
</div>
<div id="info"></div>
<script type="text/javascript">
var outDiv = document.getElementById("outDiv");
var middleDiv = document.getElementById("middleDiv");
var inDiv = document.getElementById("inDiv");
var info = document.getElementById("info");
outDiv.addEventListener("click", function () { info.innerHTML += "outDiv" + "<br>"; }, false);
middleDiv.addEventListener("click", function () { info.innerHTML += "middleDiv" + "<br>"; }, false);
inDiv.addEventListener("click", function () { info.innerHTML += "inDiv" + "<br>"; }, false);
</script>
</body>
</html>
上述是我们测试的代码,根据 info 的显示来确定触发的顺序,有三个 addEventListener,而 useCapture 可选值为 true 和 false,所以 2*2*2,可以得出 8 段不同的程序。
全为 false 时,触发顺序为:inDiv、middleDiv、outDiv;
全为 true 时,触发顺序为:outDiv、middleDiv、inDiv;
outDiv 为 true,其他为 false 时,触发顺序为:outDiv、inDiv、middleDiv;
middleDiv 为 true,其他为 false 时,触发顺序为:middleDiv、inDiv、outDiv;
……
最终得出如下结论:
true 的触发顺序总是在 false 之前;
如果多个均为 true,则外层的触发先于内层;
如果多个均为 false,则内层的触发先于外层。
上面提供代码,您可以更改其中的 true、false 值,来进行测试。注意,不适用于 IE。