事件 event 是用户操作网页时,产生的交互行为或者网页本身的一些操作。现代浏览器一般有三种事件模型

事件模型

1. 原始事件模型(DOM0级)

事件发生后,没有传播的概念,没有事件流。监听函数只是元素的一个属性值:

  1. <!-- 1. 直接在元素的值绑定 -->
  2. <button onclick="click()"></button>
  3. <!-- 2. 通过js绑定 -->
  4. <script>
  5. document.querySelector('button').onclick = function () {}
  6. </script>

优点:

  • 兼容所有浏览器

缺点:

  • 逻辑-显示未分离。
  • 同事件只能绑定一个,后绑定的会覆盖前面绑定的。

    2. IE事件模型

    IE事件仅支持冒泡,没有捕获。

事件流有两个阶段:

  1. 事件处理阶段:事件达到目标元素时,触发监听事件
  2. 事件冒泡阶段:事件从目标元素冒泡到document,并且一次检查是否有监听函数,有则执行。

示例:

  1. // 绑定事件
  2. el.attachEvent(eventType, handler)
  3. // 移除事件
  4. el.detachEvent(eventType, handler)

缺点:仅在IE中生效

3. DOM2事件模型

新增冒泡、捕获的概念,并支持一个元素节点绑定多个监听事件。

事件捕获和事件冒泡(capture、bubble)

事件 - 图1 事件捕获与事件冒泡示意图

事件流分为三个阶段:

  • 事件捕获阶段(1、2、3):事件从 document 向下传播到目标元素,依次检查节点的事件绑定并执行。
  • 事件处理阶段(4):事件到达目标元素,触发监听事件
  • 事件冒泡阶段(5、6、7):事件从目标元素向上冒泡至 document,依次检查节点的事件绑定并执行。

事件监听(addEventListener)

addEventListener 有三个参数:

  • 事件名
  • 回调函数
  • 执行阶段:为 true 则事件在捕获阶段执行,为 false 则在冒泡阶段执行。 ```javascript /**
    • addEventListener有三个参数 事件名称、事件回调、捕获/冒泡
    • 设置为true,则事件在捕获阶段执行,为false则在冒泡阶段执行。 */

btn.addEventListener(‘click’, function() { console.log(‘btn’) }, true)

box.addEventListener(‘click’, function() { console.log(‘box’) }, false) ```

事件传播

事件 发生在 DOM 元素上时,该事件并不完全发生在那个元素上。
DOM2事件模型 中的 事件捕获、处理、冒泡阶段。

事件委托(代理)

事件委托(代理)本质上利用了 事件冒泡 的机制。

事件在冒泡过程中,会上升至其父元素。
且父元素可以通过事件对象 event.target 获取到触发事件的目标节点。

因此可以将监听事件绑定在父元素,通过事件获取到子元素。
例如监听100个 <li> 的点击事件时,将事件直接绑定在其父元素 <ul> 上。

事件委托的优点:

  • 降低内存消耗,无需为每个子元素都绑定监听事件
  • 方便动态绑定事件。子元素动态增减无需单独再绑定事件。