事件传播

历史

Netscape 主张捕获方式,Microsoft 主张冒泡方式,W3C 在 DOM2 采用折中的方式,统一标准为——先捕获再冒泡。

在 DOM 中,每个事件都有 EventTarget 指向当前事件(event.target),当事件到达目标时,触发注册到这个 EventTarget 的所有监听器,但对这些监听器的执行顺序不做规范处理,某个监听器异常并不会阻止事件传播。

DOM3 事件流

  1. 捕获阶段
  2. 事件目标阶段
  3. 冒泡阶段

捕获

捕获操作是从 DOM 树的顶端(通常是 document)往下。从树顶到事件目标的 EventTargets 链是在事件初始派发时确定的,即使事件派发时树发生修改。

当一个事件被派发到捕获对象的后代时,这事件将触发从树顶到事件目标的所有捕获事件的监听器,直到向下传播到达事件目标。注册在事件目标的父节点的监听器能在事件目标接收前拦截当前事件。捕获监听器不会被注册 EventTarget 的父级的派发事件所触发。

事件捕获和事件委托模型两个区别:

  1. 事件捕获仅允许捕获方式的 EventTarget 的后代拦截。
  2. 事件捕获不是具体到某个 EventTarget,而是某个具体事件类型,一旦指定,事件捕获会拦截捕获者后代的所有此类型事件。

冒泡

冒泡方式的事件在处理完 EventTarget 后,会接着触发 EventTarget 父链上相应事件的监听器,持续向上,直到树顶,事件目标到树顶的 EventTargets 链是在事件初始派发前确定的,即使事件处理时树发生修改。

可以通过 event.bubbles 来判断当前事件是否支持冒泡。常用不冒泡的有 focus、blur、scroll。

其它

event.preventDefault,取消事件(可通过 event.cancelable 判断是可取消的),不会阻止事件传播。

event.stopPropagation() 阻止事件在捕获和冒泡阶段的进一步传播,不会阻止同级监听器接收事件。

event.stopImmediatePropagation() 阻止调用同一事件的剩余监听器,包括同级。

on-event 事件写法,html 属性(Inline 模式)和 DOM 属性(traditional 模式)都在冒泡阶段,注意覆盖。

测试

选择事件类型
一级 div

二级 p

删除1~2级

控制台察看结果