介绍事件“捕获”和“冒泡”执行顺序和事件的执行次数

本文详细介绍了JavaScript中的事件捕获和冒泡执行顺序,以及事件执行次数的计算规则。按照W3C标准,事件首先从最外层元素开始捕获,直至到达目标元素,然后冒泡回最外层。对于事件绑定在同一元素上的情况,无论事件类型和功能是否相同,都会按绑定顺序执行。事件委托是一种有效的方法,可以减少内存占用并处理动态添加的元素,但使用时需要注意避免不必要的触发。此外,`target`和`currentTarget`的区别以及如何派发事件也进行了说明。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 按照W3C标准的事件:首是进入捕获阶段,直到达到目标元素,再进入冒泡阶段
  • 事件执行次数(DOM2-addEventListener):元素上绑定事件的个数
    • 注意1:前提是事件被确实触发
    • 注意2:事件绑定几次就算几个事件,即使类型和功能完全一样也不会“覆盖”
  • 事件执行顺序:判断的关键是否目标元素
    • 非目标元素:根据W3C的标准执行:捕获->目标元素->冒泡(不依据事件绑定顺序)
    • 目标元素:依据事件绑定顺序:先绑定的事件先执行(不依据捕获冒泡标准)
    • 最终顺序:父元素捕获->目标元素事件1->目标元素事件2->子元素捕获->子元素冒泡->父元素冒泡
    • 注意:子元素事件执行前提 事件确实“落”到子元素布局区域上,而不是简单的具有嵌套关系

在一个DOM上同时绑定两个点击事件:一个用捕获,一个用冒泡。事件会执行几次,先执行冒泡还是捕获?

  • 该DOM上的事件如果被触发,会执行两次(执行次数等于绑定次数)
  • 如果该DOM是目标元素,则按事件绑定顺序执行,不区分冒泡/捕获
  • 如果该DOM是处于事件流中的非目标元素,则先执行捕获,后执行冒泡

事件的代理/委托

  • 事件委托是指将事件绑定目标元素的到父元素上,利用冒泡机制触发该事件
    • 优点:
      • 可以减少事件注册,节省大量内存占用
      • 可以将事件应用于动态添加的子元素上
    • 缺点: 使用不当会造成事件在不应该触发时触发
    • 示例:
ulEl.addEventListener('click', function(e){
    var target = event.target || event.srcElement;
    if(!!target && target.nodeName.toUpperCase() === "LI"){
        console.log(target.innerHTML);
    }
}, false);

W3C事件的 target 与 currentTarget 的区别?

  • target 只会出现在事件流的目标阶段
  • currentTarget 可能出现在事件流的任何阶段
  • 当事件流处在目标阶段时,二者的指向相同
  • 当事件流处于捕获或冒泡阶段时:currentTarget 指向当前事件活动的对象(一般为父级)

如何派发事件(dispatchEvent)?(如何进行事件广播?)

  • W3C: 使用 dispatchEvent 方法
  • IE: 使用 fireEvent 方法
var fireEvent = function(element, event){
    if (document.createEventObject){
        var mockEvent = document.createEventObject();
        return element.fireEvent('on' + event, mockEvent)
    }else{
        var mockEvent = document.createEvent('HTMLEvents');
        mockEvent.initEvent(event, true, true);
        return !element.dispatchEvent(mockEvent);
    }
}
### JavaScript DOM 事件流工作机制 #### 捕获阶段 在捕获阶段,事件从文档的根节点(`document`) 开始向下传播到目标元素所在的父级节点。此阶段的特点是事件会依次触发沿途经过的所有祖先节点上的捕获处理程序[^1]。例如,在一个嵌套结构中,如果子元素被点击,则事件首先会被其最顶层的祖先节点捕获执行相应的回调函数。 #### 目标阶段 一旦到达最终的目标元素(即发生事件的具体位置),就进入了目标阶段。在这个阶段里,只有目标元素本身能够接收到该事件,并运行它上面定义好的任何类型的监听器——无论是处于捕获模式还是冒泡模式下的处理器都会在此刻被执行[^2]。 #### 冒泡阶段 随后进入冒泡阶段,此时事件将沿着相反的方向返回至初始调用点,也就是由内部向外部逐层传递给各个容器对象直到抵达窗口级别为止[^3]。这一过程中同样允许各层次间响应各自的特定行为逻辑;不过需要注意的是并非所有的 HTML UI Events 都支持这种反方向的通知机制(如 focus/blur),因此设计应用程序时应考虑到这一点差异性影响用户体验的可能性。 以下是展示如何手动阻止默认动作以及停止进一步传播的一个简单例子: ```javascript // 获取按钮元素 const button = document.querySelector('button'); // 添加事件监听器,设置为捕获阶段 button.addEventListener('click', function(event) { console.log("Capturing Phase"); }, true); // 正常添加事件监听器,默认为冒泡阶段 button.addEventListener('click', function(event) { event.stopPropagation(); // 停止继续向上冒泡 console.log("Bubbling Phase Stopped"); }); // 测试代码效果可以尝试在一个包含多个嵌套标签的情况下观察日志输出顺序 ``` 通过以上介绍可以看出,理解这三个不同但又紧密相连的部分对于编写高效可靠的前端应用至关重要。合理利用它们可以帮助开发者实现诸如性能优化或者复杂交互等功能需求的同时也减少了不必要的冗余操作次数从而提升整体效率。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小码哥・Martin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值