理解事件流、事件冒泡、事件捕获

330 阅读3分钟

前言

看到一个问题:

addEventListener在removeListener会不会造成内存泄漏?

理解addEventListener事件监听和 removeListener移除事件监听,想一想如何更好的回答这个问题, 那么从最基础的深入去学习理解一遍之后再做解答。 于是乎,拿出JavaScript红宝书:JavaScript高级程序设计,一起来学习什么是事件。

思考理解

  • 理解事件流
  • 事件冒泡
  • 事件捕获
  • DOM事件流

Javascript与HTML的交互是通过事件实现的,事件代表文档或浏览器窗口中某个有意义的时刻,可以使用仅在事件发生时执行的监听器 订阅事件。

事件流

概念:事件流描述了页面接受事件的顺序。

但是IE和Netscape开发团队提出了完全相反的事件流方案:

  • IE将支持降事件冒泡流
  • Netscape communicator将支撑事件捕获流。

事件冒泡

概念: 事件开始的时候,由最具体的元素接受, 然后逐级向上传播到较为不具体的节点。

IE事件流被称为:事件冒泡,因为事件被定义为:从最具体的元素(文档树中最深的节点)开始触发,然后向上传播至没有那么具体的元素(文档)。

例如:

<!DOCTYPE html>
<html>
<head>
    <title> Event Bubbling Example</title>
</head>
<body>
    <div id="myDiv">Click Me</div>
</body>
</html>

点击页面中的

元素后,click事件会如下顺序发生。 1 <div>➡️ 2 <body> ➡️ 3<html> ➡️ 4 document

所有现代浏览器都支持事件冒泡,只是在实现方式上会有一些变化。IE5.5及更早版本会跳过元素(从body元素直接到document)。 现代浏览器中的事件会一直冒泡到window对象。

事件捕获

概念:事件捕获的意思是最不具体的节点应该最先收到事件,而最具体的节点应该最后收到事件。事件捕获实际上是为了在事件到达最终目标前拦截事件。

上述例子中,点击

元素后,click事件会如下顺序发生 1 document ➡️ 2<html> ➡️ 3 <body> ➡️ 4 <div>

虽然这是Netscape Communicator唯一的事件流模型,但事件捕获得到了所有现代浏览器的支持。实际上,所有浏览器都是从window对象开始捕获事件,而DOM2 Events规范规定的是从document开始

DOM事件流

DOM2 Events 规范规定事件流分为3个阶段:

  • 事件捕获:事件捕获最先发生,为提前拦截事件提供了可能
  • 到达目标:其次,实际的目标元素接收到事件。
  • 事件冒泡:最后一个阶段冒泡,最迟要在这个阶段响应事件。

在DOM事件流中,实现的目标(div元素) 在捕获阶段不会接收到事件。是因为捕获阶段从 document到 html再到body就结束了。

下一阶段,就会在div元素上触发事件的“到达目标”阶段,通常在事件处理时被认为是冒泡阶段的一部分。然后,冒泡阶段开始,事件反向传播至document。

参考阅读: 《JavaScript高级程序设计》