DOM事件流三阶段详解

事件流模型基础

DOM事件流分为三个阶段:捕获阶段、目标阶段和冒泡阶段。当事件触发时,浏览器会从文档根节点开始向下传播(捕获阶段),到达目标元素(目标阶段),再向上回溯到根节点(冒泡阶段)。

// 事件监听函数基本语法
element.addEventListener(eventType, handler, useCapture);

useCapture参数默认为false表示在冒泡阶段处理,设为true则在捕获阶段处理。

捕获阶段工作机制

事件从window对象开始向下传播至目标元素父级。捕获阶段的事件监听器会按照DOM树从上到下的顺序执行。适合用于需要优先处理全局事件或事件拦截的场景。

<div id="grandparent">
  <div id="parent">
    <div id="child"></div>
  </div>
</div>

<script>
document.getElementById('grandparent').addEventListener('click', () => {
  console.log('Grandparent captured');
}, true);

document.getElementById('parent').addEventListener('click', () => {
  console.log('Parent captured');
}, true);
</script>

点击child元素时控制台输出顺序为:Grandparent → Parent。

目标阶段特性

当事件到达目标元素时,无论useCapture如何设置,注册在目标元素上的事件处理程序都会执行。目标阶段没有单独的API控制,执行顺序取决于代码注册顺序。

const child = document.getElementById('child');
child.addEventListener('click', () => console.log('Child bubble'));
child.addEventListener('click', () => console.log('Child capture'), true);

两个处理程序按注册顺序执行,与useCapture参数无关。

冒泡阶段运行原理

事件从目标元素向上传播至文档根节点。大多数事件都会冒泡(focus/blur等除外),这是默认的事件处理阶段。

document.getElementById('parent').addEventListener('click', () => {
  console.log('Parent bubbled');
});

document.getElementById('grandparent').addEventListener('click', () => {
  console.log('Grandparent bubbled');
});

点击child元素时输出顺序为:Parent → Grandparent。

事件传播控制方法

event.stopPropagation()可阻止事件继续传播,但不会阻止同阶段的其他监听器执行。event.stopImmediatePropagation()会立即停止所有后续监听器。

element.addEventListener('click', (e) => {
  e.stopPropagation();
  console.log('This will execute');
});

element.addEventListener('click', () => {
  console.log('This won\'t execute if stopImmediatePropagation was called');
});

实际应用场景

表单验证适合在冒泡阶段处理,可以统一管理提交事件。组件库中的事件代理通常在捕获阶段实现,便于优先处理系统级行为。自定义事件系统可能需要同时利用两个阶段实现复杂交互逻辑。

// 事件委托示例
document.addEventListener('click', (e) => {
  if(e.target.matches('.dynamic-element')) {
    handleDynamicElementClick();
  }
}, false); // 冒泡阶段处理

性能优化建议

避免在大量元素上单独绑定事件,使用事件委托可以减少内存占用。谨慎使用事件阻止传播,可能影响其他插件功能。合理选择处理阶段可以减少不必要的事件处理调用。

// 性能较差的做法
document.querySelectorAll('.items').forEach(item => {
  item.addEventListener('click', handler);
});

// 更好的做法
document.body.addEventListener('click', (e) => {
  if(e.target.closest('.items')) {
    handler(e);
  }
});

BbS.okacop092.info/PoSt/1120_862426.HtM
BbS.okacop093.info/PoSt/1120_795222.HtM
BbS.okacop094.info/PoSt/1120_403770.HtM
BbS.okacop095.info/PoSt/1120_330391.HtM
BbS.okacop096.info/PoSt/1120_772495.HtM
BbS.okacop097.info/PoSt/1120_138349.HtM
BbS.okacop098.info/PoSt/1120_310005.HtM
BbS.okacop099.info/PoSt/1120_326759.HtM
BbS.okacop114.info/PoSt/1120_973647.HtM
BbS.okacop829.info/PoSt/1120_355246.HtM
BbS.okacop092.info/PoSt/1120_109200.HtM
BbS.okacop093.info/PoSt/1120_835870.HtM
BbS.okacop094.info/PoSt/1120_379605.HtM
BbS.okacop095.info/PoSt/1120_100242.HtM
BbS.okacop096.info/PoSt/1120_970427.HtM
BbS.okacop097.info/PoSt/1120_461828.HtM
BbS.okacop098.info/PoSt/1120_035281.HtM
BbS.okacop099.info/PoSt/1120_422471.HtM
BbS.okacop114.info/PoSt/1120_751650.HtM
BbS.okacop829.info/PoSt/1120_768620.HtM
BbS.okacop092.info/PoSt/1120_055547.HtM
BbS.okacop093.info/PoSt/1120_564318.HtM
BbS.okacop094.info/PoSt/1120_246834.HtM
BbS.okacop095.info/PoSt/1120_494875.HtM
BbS.okacop096.info/PoSt/1120_425370.HtM
BbS.okacop097.info/PoSt/1120_208669.HtM
BbS.okacop098.info/PoSt/1120_127632.HtM
BbS.okacop099.info/PoSt/1120_796985.HtM
BbS.okacop114.info/PoSt/1120_364155.HtM
BbS.okacop829.info/PoSt/1120_625302.HtM
BbS.okacop092.info/PoSt/1120_048402.HtM
BbS.okacop093.info/PoSt/1120_930793.HtM
BbS.okacop094.info/PoSt/1120_970116.HtM
BbS.okacop095.info/PoSt/1120_254771.HtM
BbS.okacop096.info/PoSt/1120_275367.HtM
BbS.okacop097.info/PoSt/1120_764601.HtM
BbS.okacop098.info/PoSt/1120_045119.HtM
BbS.okacop099.info/PoSt/1120_973409.HtM
BbS.okacop114.info/PoSt/1120_984615.HtM
BbS.okacop829.info/PoSt/1120_851966.HtM
BbS.okacop092.info/PoSt/1120_543950.HtM
BbS.okacop093.info/PoSt/1120_389035.HtM
BbS.okacop094.info/PoSt/1120_402256.HtM
BbS.okacop095.info/PoSt/1120_882156.HtM
BbS.okacop096.info/PoSt/1120_720984.HtM
BbS.okacop097.info/PoSt/1120_452522.HtM
BbS.okacop098.info/PoSt/1120_780605.HtM
BbS.okacop099.info/PoSt/1120_018386.HtM
BbS.okacop114.info/PoSt/1120_928856.HtM
BbS.okacop829.info/PoSt/1120_877929.HtM
BbS.okacop000.info/PoSt/1120_462878.HtM
BbS.okacop001.info/PoSt/1120_449632.HtM
BbS.okacop002.info/PoSt/1120_188549.HtM
BbS.okacop003.info/PoSt/1120_174016.HtM
BbS.okacop004.info/PoSt/1120_878732.HtM
BbS.okacop005.info/PoSt/1120_590062.HtM
BbS.okacop006.info/PoSt/1120_648373.HtM
BbS.okacop007.info/PoSt/1120_048637.HtM
BbS.okacop008.info/PoSt/1120_479245.HtM
BbS.okacop009.info/PoSt/1120_449627.HtM
BbS.okacop000.info/PoSt/1120_323781.HtM
BbS.okacop001.info/PoSt/1120_385038.HtM
BbS.okacop002.info/PoSt/1120_932312.HtM
BbS.okacop003.info/PoSt/1120_256893.HtM
BbS.okacop004.info/PoSt/1120_093492.HtM
BbS.okacop005.info/PoSt/1120_039309.HtM
BbS.okacop006.info/PoSt/1120_462883.HtM
BbS.okacop007.info/PoSt/1120_270394.HtM
BbS.okacop008.info/PoSt/1120_628242.HtM
BbS.okacop009.info/PoSt/1120_338930.HtM
BbS.okacop000.info/PoSt/1120_286817.HtM
BbS.okacop001.info/PoSt/1120_967573.HtM
BbS.okacop002.info/PoSt/1120_068695.HtM
BbS.okacop003.info/PoSt/1120_551706.HtM
BbS.okacop004.info/PoSt/1120_943587.HtM
BbS.okacop005.info/PoSt/1120_304817.HtM
BbS.okacop006.info/PoSt/1120_911834.HtM
BbS.okacop007.info/PoSt/1120_298918.HtM
BbS.okacop008.info/PoSt/1120_662749.HtM
BbS.okacop009.info/PoSt/1120_661025.HtM

#牛客AI配图神器#

全部评论

相关推荐

一只乌鸦:这不才9月吗,26到明年毕业前能一直找啊,能拿下提前批,转正的,offer打牌的都是有两把刷子的,为什么非要跟他们比。如果别人是9本硕+金牌+好几段大厂实习呢?如果别人是双非通天代呢?如果别人是速通哥呢?,做好自己就行了,我们做不到他们一样提前杀死比赛,但晚点到终点也没啥关系吧
双非应该如何逆袭?
点赞 评论 收藏
分享
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务