事件捕获和事件冒泡
了解DOM 事件机制机制首先需要知道什么是捕获,什么是冒泡。
在这里可以使用一个点击事件举例说明:
//HTML
<div class="A1">
<div class="A2">
<div class="A3">
文字
</div>
</div>
</div>
假设现在给这三个层叠的div分别添加事件监听fn1 / fn2 / fn3 ,那么问题来了:
点击文字内容是算哪一个div呢?
点击文字最先调用fn1 / fn2 / fn3哪个事件呢?
答案是:都算;都行。
为什么?
2002年,W3C发布标准 文档名为DOM Level 2 Events Specification规定 浏览器应该同时支持两种调用顺序。
首先按A1=>A2=>A3顺序看有没有函数监听,
然后按A3=→>A2=>A1顺序看有没有函数监听有监听函数就调用,并提供事件信息,没有就跳过。
术语上来讲
从外向内找监听函数,叫 事件捕获
从内向外找监听函数,叫 事件冒泡
事件传递有两种方式:冒泡与捕获
事件传递定义了元素事件触发的顺序。如果将<p>元素插入到<div>元素中,用户点击<p>元素,哪个元素的“click”事件先被触发呢?
在冒泡中,内部元素的事件会先被触发,然后再触发外部元素,即:<p>元素的点击事件先触发,然后会触发
元素的点击事件。
在捕获中,外部元素会先被触发,然后才会触发内部元素的事件,即:<div>元素的点击事件先触发,然后再触发<p>元素的点击事件。
addEventListener() 方法可以指定 "useCapture" 参数来设置传递类型:
addEventListener( event, function, useCapture);
默认值为 false, 即冒泡传递,当值为 true 时, 事件使用捕获传递。
document.querySelector("myDiv").addEventListener("click", myFunction, true);
在事件传播的过程当中事件捕获不可以取消,而事件冒泡可以取消。
在事件流当中使用target.stopPropagation()可以中断冒泡。
特殊情况下的监听顺序
一般存在捕获和冒泡两种事件时是先捕获优先于冒泡。
前提: 只有一个div存在且被监听(不考虑上下级元素同时被监听)
fn 分别在捕获阶段和冒泡阶段监听click事件、用户点击的元素就是开发者监听的
div.addEventLisenter('click', f1)
div.addEventLisenter('click', f2, true)
请问,这时候 f1 先执行还是 f2 先执行?
答案:谁先监听谁先执行,所以是f1。
如果把两行调换位置后,先执行的也是前面一行的
总结:这是一个特例