事件模型

1. 事件与事件流

由于 DOM 是树结构,当父子节点都绑定了事件时,触发子节点会引出事件流的概念:事件会在节点之间按特定顺序传播。

事件流都经历三个阶段:

  • 捕获阶段:从最外层向目标元素传播(window → document → ... → 目标父级)。

  • 目标阶段:事件到达实际触发的目标元素。

  • 冒泡阶段:从目标元素向外传播(与捕获相反)。

  • 事件冒泡:从最具体的节点(触发节点)逐渐向上传播到最不具体的节点(DOM 最高层)。

  • 事件捕获:与冒泡相反,最具体的节点最后收到事件。

2. 事件模型分类

事件模型可分为三种:原始事件模型(DOM0)、标准事件模型(DOM2)、IE 事件模型(已废弃)。

2.1 原始事件模型(DOM0)

两种绑定方式:

// HTML 内联
<input type="button" onclick="fun()">

// JS 属性绑定
var btn = document.getElementById('btn');
btn.onclick = fun;

支持的事件类型有:onclick、onmouseover、onmouseout、onkeydown、onmouseenter、onmouseleave、onchange、onkeyup、onload、onerror、onscroll、onresize、onblur 等。

特性:跨浏览器优势、绑定速度快;但页面可能未完全加载就绑定,导致事件不生效。删除时把对应事件属性置为 null 即可。

2.2 标准事件模型(DOM2)

事件绑定监听函数:

addEventListener(eventType, handler, useCapture);
removeEventListener(eventType, handler, useCapture);
  • 第三个参数 useCapture 为 true:捕获阶段执行;为 false:冒泡阶段执行。
  • event.eventPhase:1 = 捕获阶段、2 = 目标阶段、3 = 冒泡阶段。

补充:DOM2 的优点是支持多次绑定同一个事件(按注册顺序执行),且能用 stopPropagation() 阻止传播、preventDefault() 阻止默认行为,是目前主流的写法。

3. 三种模型对比

模型写法多次绑定冒泡/捕获主流
DOM0el.onclick = fn否仅冒泡历史
DOM2addEventListener是可选主流
IE 模型attachEvent(已废弃)是仅冒泡不推荐

来源整理自:vue3js.cn 面试官系列