事件流就是事件的传播机制,描述的是从页面中接受事件的顺序。
当你点击一个按钮时,单击事件不仅仅发生在按钮上,也单击了按钮的容器元素,甚至也单击了整个页面。
<div class="outer">
<div class="center">
<div class="inner"></div>
</div>
</div>
let outer = document.getElementsByClassName('outer')[0],
center = document.getElementsByClassName('center')[0],
inner = document.getElementsByClassName('inner')[0];
outer.onclick = function() {
console.log('outer')
}
center.onclick = function() {
console.log('center')
}
inner.onclick = function() {
console.log('inner')
}
点击 OUTER 输出 outer,点击 CENTER 输出 outer、center,点击 INNER 输出 outer、center、inner
1. 事件冒泡
事件冒泡,即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接受,然后沿 DOM 树逐级向上传播到较为不具体的节点(文档)。IE 低版本浏览器只冒泡到 document 为止,IE9 及其它浏览器会冒泡到 window 对象。
IE 低版本的事件流,只支持事件冒泡。
2. 事件捕获
事件捕获的思想是不太具体的节点应该先接受到事件,然后沿 DOM 树依次向下,而最具体的节点应该是最后接受到事件。事件捕获的用意在于在事件到达预定目标之前捕获它。
尽管 DOM 2 级事件规范要求事件应该从 document 对象开始传播,但是大多浏览器都是从 window 对象开始捕获事件。
3. DOM 事件流
DOM 2 级事件规定的事件流包括三个阶段:
事件捕获阶段
处于目标阶段
事件冒泡阶段
首先发生的是事件捕获,为截获事件提供了机会,然后实际目标接受到事件,最后是冒泡阶段,可以在这里对事件做出响应。
即使 DOM 2 级事件规范明确要求捕获阶段不会涉及事件目标,但是大多数浏览器都会在捕获阶段触发事件对象上的事件,结果就是有两个机会在目标对象上操作事件。
捕获阶段:
从最外层开始查找 -> document -> outer -> center -> inner 捕获到精确的哪个元素触发事件
冒泡阶段:
从最里层元素开始 -> inner -> center -> outer -> document -> window 一直冒泡到最外层
使用 on 的事件都是 DOM 0 级事件,事件绑定函数的执行,都是在冒泡阶段,只要绑定了事件函数,就会按照冒泡顺序执行,单击事件会比双击事件先触发执行。
DOM 2级事件,可以通过传入第三个参数,来将函数绑定在捕获阶段或者冒泡阶段执行。
4. 取消冒泡
使用事件对象的 stoppropagation()
方法,可以阻止冒泡,但是 IE 的事件对象不支持这种方法,IE 的事件对象中,可以使用将 cancelBubble
属性置为 true
来阻止。
inner.onclick = function(e) {
e = e || window.event;
e.stopPropagation ? e.stopPropagation() : e.cancelBubble = true
}