0%

事件捕获和事件冒泡--关于Chrome改版

概述


  • DOM事件标准定义了两种事件流(就是事件发生顺序):捕获和冒泡
  • 它们几乎是相反的概念事件冒泡和事件捕获分别由微软和网景公司提出

    DOM事件触发的三个阶段

当一个DOM事件被触发时,它不仅仅只是单纯地在本身对象上触发一次,而是会经历三个不同的阶段:

1.捕获阶段:先由文档的根节点document往事件触发对象,从外向内捕获事件对象;

2.目标阶段到达目标事件位置(事发地),触发事件;

3.冒泡阶段:再从目标事件位置往文档的根节点方向回溯从内向外冒泡事件对象。

addEventListener方法


事件捕获阶段和冒泡阶段的处理函数,
都使用addEventListener()方法指定

1
element.addEventListener(event, function, useCapture)
  • 该方法用来为元素绑定事件处理函数
  • 其第三个参数是:‘控制事件阶段’,boolean类型
  • 默认是false,表示在事件冒泡的阶段调用事件处理函数
  • 若传入true,就表示在事件捕获的阶段调用事件处理函数

    阻止事件冒泡


w3c的方法是e.stopPropagation(),IE则是使用e.cancelBubble = true

  • 在事件处理函数中添加一个会默认传入的参数event,然后使用e.stopPropagation()
  • cancelBubble()同理

    捕获事件和冒泡事件优先级?


当前时间:2021.05.26

过去版本的事件触发顺序

  • 了解DOM事件触发的三个阶段后,我们应该知道,是一次经历捕获阶段,目标阶段,冒泡阶段,因此先捕获,后冒泡
  • 而在目标阶段,将按照元素上–绑定事件(监听器)注册的顺序触发。(即代码先后顺序)

图片

以往的发生顺序,取决于冒泡和捕获事件的代码位置的先后顺序–

Chrome 89.0.4363.0 以及之后版本:

目标元素(目标阶段)的触发事件顺序不再按照注册顺序触发!而是按照先捕获再冒泡的顺序依次执行!

经查证,Chrome、微软Edge已经采用该这种规范。而火狐、IE仍未兼容这一改动。

举个栗子🌰

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<div>
    <button>123</button>
</div>
<script>
  var btn = document.querySelector('button');
  var div = document.querySelector('div');
  btn.addEventListener('click', function () {
    console.log('bubble', 'btn');
  }, false);
  btn.addEventListener('click', function () {
    console.log('capture', 'btn');
  }, true);
  div.addEventListener('click', function () {
    console.log('bubble', 'div');
  }, false);
  div.addEventListener('click', function () {
    console.log('capture', 'div');
  }, true);
</script>

点击btn后,过去版本以及火狐、IE触发顺序为:

1
2
3
4
capture div
bubble btn
capture btn
bubble div

而最新版Chrome、微软Edge的触发顺序为:

1
2
3
4
capture div
capture btn
bubble btn
bubble div

兼容各浏览器

先捕获后冒泡的顺序注册目标元素上绑定的监听事件,以使所有浏览器上事件触发顺序一致

参考:

事件捕获与事件冒泡优先级

浅谈事件冒泡和事件捕获

Chrome 89 更新事件触发顺序,导致99%的文章都错了(包括MDN)– 蓝色的秋风 | 思否