事件捕捉与事件冒泡 - JavaScript事件处理
事件冒泡的执行顺序
冒泡原理:当一个事件发生在一个元素上,它会首先运行在该元素上的处理程序,然后运行其父元素上的处理程序,然后一直向上到其他祖先上的处理程序。
<div onclick="alert('执行')">
<em>当你点击这个<code>EM</code>的时候, 上面<code>DIV</code>的点击事件也会执行</em>
</div>我们再测试一个更加复杂的嵌套
<style>
body * {margin: 10px;border: 1px solid blue;}
</style>
<form onclick="alert('form')">FORM
<div onclick="alert('div')">DIV
<p onclick="alert('p')">P</p>
</div>
</form>当使用事件捕获时,父级元素先触发,子级元素后触发,click事件捕捉的顺序为:document→html→body→div→p。
当使用事件冒泡时,子级元素先触发,父级元素后触发,click事件冒泡的顺序为:p→div→body→html→document。
并不是所有的事件都能冒泡,以下事件不冒泡:blur、focus、load、unload。
事件传播概述
当一个 HTML 事件触发时,其传播过程遵循特定的顺序:先经过捕获阶段,接着到达目标阶段,最后经历冒泡阶段。这一机制使得事件可以在 DOM 树中自上而下(捕获)或自下而上(冒泡)传播,从而触发沿途关联的事件处理程序。
事件传播阶段
捕获阶段: 事件从文档根节点(通常是 document)开始向外层元素逐层向下传播,直至到达目标元素。在此过程中,已注册捕获阶段监听(使用 {capture: true} 或 addEventListener(..., true))的处理程序将被依次调用。
目标阶段: 事件到达目标元素(event.target),即引发事件的最深层嵌套元素。此时,直接绑定在目标元素上的事件处理程序将被执行。
冒泡阶段: 事件从目标元素开始向上传播,经过所有包含它的祖先元素,直至抵达文档根节点。在此阶段,未指定捕获的事件处理程序(通过 on<event> 特性、HTML 属性或 addEventListener(..., false) / {capture: false} 添加)将按照事件冒泡路径依次触发。
事件对象属性
事件处理程序可以访问事件对象上的以下关键属性:
event.target:引发事件的最深层嵌套元素。
event.currentTarget(通常等于 this):当前正在处理事件的元素,即绑定了当前执行事件处理程序的元素。
event.eventPhase:表示事件当前所处的阶段,取值为 1(捕获)、2(目标)或 3(冒泡)。
阻止事件传播
任何事件处理程序都可以通过调用 event.stopPropagation() 阻止事件继续向上(捕获阶段)或向下(冒泡阶段)传播。然而,除非有明确需求,否则不建议轻易阻止事件传播,因为其他处理程序可能依赖于这些事件来完成其功能。
捕获阶段的实际应用与事件委托
尽管捕获阶段相对较少使用,但它为事件委托提供了基础。事件委托是一种高效事件处理模式,允许在父元素上设置单个事件处理器,以处理其所有子元素的同类事件。通过监听捕获阶段,父元素的处理器能在事件到达子元素之前优先响应,根据事件的目标元素(event.target)做出相应的处理。这种做法有助于减少内存消耗和提升性能,特别是在动态添加或删除子元素的场景中。
文档如有描述不清楚、错误或者过时的地方,欢迎留言指出。
文档、教程内容会不定时更新,转载请标明原帖链接,以免让过时的教程流入网络。
