当一个HTML 元素产生一个事件时,该事件会在元素节点与根节点之间按照特定的路径传播,路径所经过的所有节点都会接收到该操作,这个传播过程可称为 DOM 事件流。简单来说,事件流就是从页面中接收事件的顺序,而事件流又分为事件冒泡和事件捕获。
1.事件冒泡
事件冒泡即开始由最具体的元素接受,然后逐级向上传播到较为不具体的节点。它是一个向上传播的过程。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Dom</title>
</head>
<body>
<div id="myDiv">点击我</div>
</body>
</html>
如果点击页面中的
元素,那么这个click 事件会按照如下顺序传播:
——> ——> ——> document
click 事件首先在
click 事件首先在
元素上发生,而这个元素就是我们单击的元素。然后,click事件会沿着 DOM 树向上传播,在每一级节点上都会发生,直至传播到 documnt 对象。
在事件捕捉过程中,documnt对象最先接收到click 事件,然后沿着 DOM 树依次向下,一直传播到事件的具体目标,即
2.事件捕捉
事件捕捉则是与事件冒泡完全相反的过程,它是由最不具体的元素先接收事件,而具体的元素则是最后接收事件。它是一个向下传播的过程。
事件捕捉,单击click会按照如下顺序传播:
document** ——> ——> ——> **
在事件捕捉过程中,documnt对象最先接收到click 事件,然后沿着 DOM 树依次向下,一直传播到事件的具体目标,即
元素。
3.DOM事件流
DOM标准规定事件流包括三个阶段: 事件捕捉阶段、处于目标阶段 和 事件冒泡阶段。
- 事件捕获阶段:实际目标()在捕获阶段不会接收事件。也就是在捕获阶段,事件从document到再到就停止了。上图中为1~3.
- 处于目标阶段:事件在上发生并处理。但是事件处理会被看成是冒泡阶段的一部分。
-
4.事件代理
事件代理,又称之为事件委托。是JavaScript中常用绑定事件的常用技巧。顾名思义,“事件代理”即是把原本需要绑定在子元素的响应事件委托给父元素,让父元素担当事件监听的职务。事件代理的原理是DOM元素的事件冒泡。
事件委托的优点
1.可以大量节省内存占用,减少事件注册,比如在ul上代理所有li的click事件就非常棒
<ul id="list">
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
......
<li>item n</li>
</ul>
// ...... 代表中间还有未知数个 li
2.可以实现当新增子对象时无需再次对其绑定(动态绑定事件)
HTML代码块:<ul id="myLinks">
<li id="goSomewhere">Go somewhere</li>
<li id="doSomething">Do something</li>
<li id="sayHi">Say hi</li>
</ul>
原生js做法:
var item1 = document.getElementById("goSomewhere");
var item2 = document.getElementById("doSomething");
var item3 = document.getElementById("sayHi");
item1.onclick = function() {
location.href = "http://www.baidu.com";
};
item2.onclick = function() {
document.title = "事件委托";
};
item3.onclick = function() {
alert("hi");
};
事件代理:
var item1 = document.getElementById("goSomewhere");
var item2 = document.getElementById("doSomething");
var item3 = document.getElementById("sayHi");
document.addEventListener("click", function (event) {
var target = event.target;
switch (target.id) {
case "doSomething":
document.title = "事件委托";
break;
case "goSomewhere":
location.href = "http://www.baidu.com";
break;
case "sayHi": alert("hi");
break;
}
})
使用事件委托注意事项
使用“事件委托”时,并不是说把事件委托给的元素越靠近顶层就越好。事件冒泡的过程也需要耗时,越靠近顶层,事件的”事件传播链”越长,也就越耗时。如果DOM嵌套结构很深,事件冒泡通过大量祖先元素会导致性能损失。