在 JavaScript 中,事件传播描述的是从发起事件的元素到其他元素的事件传递的过程。

事件传播的两个主要阶段是捕获阶段和冒泡阶段。

事件传播模型允许事件在 DOM 中以特定的顺序传播,这对于控制事件处理的顺序和方式非常重要。

事件传播的三个阶段:

  1. 捕获阶段 (Capturing Phase):事件从document对象向下传播到事件目标的过程被称为捕获阶段。它的目的是先通知最外层的元素,然后依次向内层元素传播。

  2. 目标阶段 (Target Phase):处于目标阶段时,事件到达了触发事件的元素。在这个阶段,可以在目标元素上触发事件处理器。

  3. 冒泡阶段 (Bubbling Phase):事件从事件目标向上冒泡回document对象的过程被称为冒泡阶段。与捕获阶段相反,冒泡阶段先通知最内层的元素,然后依次向外层元素传播。

使用 addEventListener 来指定事件在哪个阶段处理:

当你使用 addEventListener 方法时,你可以指定一个布尔值作为第三个参数来决定该监听器是在捕获阶段还是冒泡阶段被触发。

  • 如果设置为 true,事件处理程序将在捕获阶段执行。
  • 如果设置为 false 或省略,事件处理程序将在冒泡阶段执行。
// 捕获阶段监听事件
document.getElementById("parent").addEventListener(
  "click",
  function () {
    console.log("Parent clicked - Capturing Phase");
  },
  true
);
 
// 冒泡阶段监听事件
document.getElementById("child").addEventListener(
  "click",
  function (event) {
    console.log("Child clicked - Bubbling Phase");
  },
  false
);

在这个示例中,如果 child 元素被点击,您将看到以下顺序的输出:

Parent clicked - Capturing Phase
Child clicked - Bubbling Phase

阻止事件传播:

有时你可能不想让事件继续传播,这可以通过调用事件对象上的 stopPropagation() 方法来实现。

// 在 child 节点上阻止事件冒泡
document.getElementById("child").addEventListener(
  "click",
  function (event) {
    console.log("Child clicked - No further propagation");
    event.stopPropagation();
  },
  false
);

如果再次点击 child 元素,就会触发 child 的点击处理程序,但不会触发 parent 的点击处理程序,因为事件传播已经被停止。

阻止默认行为:

此外,事件对象还提供了一个 preventDefault() 方法,它允许你阻止事件的默认行为。举例来说,这通常用于表单提交事件,以防止表单的默认提交行为:

document.getElementById("myForm").addEventListener("submit", function (event) {
  console.log("Form submission cancelled.");
  event.preventDefault();
});

这些是事件传播的基础知识,了解这一概念非常重要,因为它允许开发者控制事件的流向,从而根据需要创建复杂的事件处理逻辑。