事件冒泡与捕获

742 阅读3分钟

事件冒泡与事件捕获分别有微软与网景公司提出,这两个概念主要是为了解决事件流(事件发生顺序)的一些问题。 考虑下如下代码

<div id="outter">
  <div id="inner"> click me </div>
</div>

如果我为id为outter与inner的两个节点都添加click事件,哪个会首先触发呢?

...

为了解决上面的问题,微软与网景分别提出了两种几乎完全相反的解决方案,也就是上面提到的冒泡与捕获

事件冒泡

事件冒泡这个概念是有微软提出的解决事件流的方案,具体执行过程是由内层元素触发,一直向上传播直到document对象。类似于我们一个石头扔进河里,水泡由水底冒出水面的效果一样。

因此,在id为inner标签上发生click事件的顺序是 div(id=inner) => div(id=outter) => body => html => document

事件捕获

网景提出另一种事件流名为事件捕获(event capturing)。与事件冒泡相反,事件会从最外层开始发生,直到最具体的元素。

因此在事件捕获的概念下在div标签上发生click事件的顺序应该是document => html => body => div(id=outter) => div(id=inner)

addEventListener

网景 和 微软 曾经的战争还是比较火热的,当时, 网景主张捕获方式,微软主张冒泡方式。后来 w3c 采用折中的方式,平息了战火,制定了统一的标准——先捕获再冒泡。

addEventListener的第三个参数就是为冒泡和捕获准备的.

addEventListener有三个参数:

element.addEventListener(event, function, useCapture)

event: 绑定的事件

function: 触发事件的回调函数

useCapture: false 默认值 冒泡阶段 true 为捕获阶段

事件冒泡 vs 事件捕获

当事件冒泡与事件捕获同时存在的情况,事件又是如何执行的呢? 思考如下代码

<style>
#box {
  width: 100px;
  height: 100px;
  background-color: red;
}
#box-conent {
  width: 100px;
  height: 50px;
  background-color: black;
}
</style>
  
<div id="box">
  <div id="box-conent"></div>
</div>
<script>
  var obox = document.getElementById("box");
  var oboxCon = document.getElementById('box-content');
  obox.addEventListener('click', function(ev) {
    console.log(ev.target)
    console.log(ev.currentTarget)
    console.log('冒泡')
  }, false)
  obox.addEventListener('click', function(ev){
    console.log(ev.target)
    console.log(ev.currentTarget)
    console.log('委托1')
  }, true)
  obox.addEventListener('click', function(ev){
    console.log(ev.target)
    console.log(ev.currentTarget)
    console.log('委托2')
  }, true)
</script>

box盒子宽高100 * 100, box-content盒子宽高 100 * 50。

下面思考一下,点击box-content盒子时,上面代码输出结果是什么?

点击box盒子时,输出结果又是什么?为什么?

...

通过思考、测试我们发现

点击box-content时,输出结果依次是

 委托1  
 委托2
 冒泡

执行过程中上面ev.target 与ev.currentTarget 结果有什么变化?

ev.target 输出 <div id="box-conent"></div>

ev.currentTarget 输出 <div id="box"><div id="box-conent"></div></div>

点击box时,输出结果依次是

冒泡
委托1  
委托2

执行过程中上面ev.target 与ev.currentTarget 结果有什么变化?

ev.target 输出 <div id="box"><div id="box-conent"></div></div>

ev.currentTarget 输出 <div id="box"><div id="box-conent"></div></div>

执行完后,我们要了解ev.target与ev.currentTarget

ev.target与ev.currentTarget

ev.target 触发事件的对象(目标对象)

ev.currentTarget 添加事件的对象

我们是否可以这么解释??

e.target == e.currentTarget 执行顺序根据注册事件时的顺序执行

e.target != e.currentTarget 执行顺序为先执行捕获阶段,捕获目标对象,而后再执行冒泡阶段

如有侵权,请发邮箱至wk_daxiangmubu@163.com 或留言,本人会在第一时间与您联系,谢谢!!

微信公众号