事件捕获与冒泡执行顺序

同一 DOM 元素同时绑定捕获和冒泡事件的执行机制

问题

给一个 DOM 元素同时绑定两个点击事件,一个使用捕获,一个使用冒泡,会执行几次事件?先执行捕获还是冒泡?

解答

执行次数

addEventListener 绑定几次就执行几次。如果同时绑定捕获和冒泡事件,会执行 2 次。

const element = document.getElementById('box');

// 捕获阶段
element.addEventListener('click', () => {
  console.log('捕获阶段');
}, true);

// 冒泡阶段
element.addEventListener('click', () => {
  console.log('冒泡阶段');
}, false);

// 点击 element 后输出:
// 捕获阶段
// 冒泡阶段

执行顺序

先执行捕获,后执行冒泡。

事件流的完整过程:捕获阶段 → 目标阶段 → 冒泡阶段。

const parent = document.getElementById('parent');
const child = document.getElementById('child');

parent.addEventListener('click', () => {
  console.log('父元素 - 捕获');
}, true);

child.addEventListener('click', () => {
  console.log('子元素 - 捕获');
}, true);

child.addEventListener('click', () => {
  console.log('子元素 - 冒泡');
}, false);

parent.addEventListener('click', () => {
  console.log('父元素 - 冒泡');
}, false);

// 点击 child 后输出:
// 父元素 - 捕获
// 子元素 - 捕获
// 子元素 - 冒泡
// 父元素 - 冒泡

关键点

  • addEventListener 绑定几次就执行几次,捕获和冒泡算两次独立绑定
  • 事件执行顺序:先捕获后冒泡
  • addEventListener 第三个参数为 true 表示捕获阶段触发,false 或不传表示冒泡阶段触发
  • 在目标元素上,多个事件按绑定顺序执行,不区分捕获或冒泡