DOM事件流(event flow )分为以下三个阶段:
事件捕获阶段
事件捕获(event capturing):意思是当鼠标点击或者触发dom事件的时候,浏览器会从这个事件的元素根节点开始一层一层的传播至当前元素,即我们触发了这个元素,如果它的父元素通过事件捕获方式注册了对应的事件的话,会先触发父元素绑定的事件。
处于目标阶段
事件到达目标节点时,就到了目标阶段,事件在目标节点上被触发
事件冒泡阶段
事件冒泡(dubbed bubbling):与事件捕获恰恰相反,事件冒泡顺序是由内到外进行事件传播,直到根节点,也就是说从目前元素开始一级一级往上进行事件传播。
不支持冒泡的事件有
- UI事件
load, unload,scroll,resize - 焦点事件
blur, focus - 鼠标事件
mouseleave, mouseenter**
支持冒泡的事件有
- 点击事件
click ,dbclick , - 键盘事件
keydown ,keyup , - 鼠标事件
mousedown ,mousemove ,mouseout ,mouseover ,mouseup ,scroll
在如下结构中
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>事件冒泡与捕获示例</title>
<style>
#parent {
padding: 20px;
background-color: lightblue;
}
#child {
padding: 10px;
background-color: coral;
}
#output {
margin-top: 20px;
white-space: pre-wrap; /* 保持换行 */
}
</style>
</head>
<body>
<div id="parent">
<button id="child">点击我</button>
</div>
<pre id="output"></pre>
<script>
const output = document.querySelector("#output");
// 事件冒泡示例
function parentClick() {
output.textContent += "父元素被点击(冒泡)\n";
}
function childClick() {
output.textContent += "子元素被点击(冒泡)\n";
}
// 在父,子元素上添加点击事件处理器(冒泡)
document.getElementById("parent").addEventListener("click", parentClick);
document.getElementById("child").addEventListener("click", childClick);
// 事件捕获示例
function parentClickCapture() {
output.textContent += "父元素被点击(捕获)\n";
}
function childClickCapture() {
output.textContent += "子元素被点击(捕获)\n";
}
// 在父,子元素上添加捕获阶段的点击事件处理器
document.getElementById("parent").addEventListener("click", parentClickCapture, true);
document.getElementById("child").addEventListener("click", childClickCapture, true);
</script>
</body>
</html>
addEventListener方法的第三个参数useCapture(通常称为true或false)用于指定事件处理程序是在事件的捕获阶段还是在冒泡阶段执行。
当我们点击按钮时,输出将显示:
- 首先,捕获阶段的事件处理程序被调用,从父元素开始,然后是子元素。
- 接着,目标元素(子元素)的冒泡阶段处理程序被调用,然后是父元素的冒泡阶段处理程序。
dom标准事件流的触发的先后顺序为:先捕获再冒泡,即每当我们进行事件触发的时候,先进行捕获事件的触发,再进行冒泡。目前除IE10及以下不支持捕获型事,其他浏览器如IE11、Chrome 、Firefox、Safari等浏览器则同时存在。