JavaScript 事件冒泡和捕捉

JavaScript 事件冒泡和捕捉

在JavaScript中,事件的传播是通过’事件流’来实现的。事件流是特定网页接收事件的顺序。因此,在JS中,事件流的处理取决于三个方面:

事件捕捉

事件目标

事件冒泡

在这一部分中,我们将学习并讨论两个方面,即 事件冒泡事件捕捉 。我们将逐个实际学习这些概念。

事件冒泡

在使用JavaScript开发网页或网站时,使用事件冒泡的概念,当一个元素嵌套在另一个元素上并且是相同事件的一部分时,事件处理程序被调用。这种技术或方法被称为事件冒泡。因此,在执行网页的事件流时,使用事件冒泡。我们可以理解事件冒泡为当一个元素嵌套在另一个元素中时,从最深的元素开始,沿着其父元素并一直到最上层的所有祖先元素,执行调用。

事件冒泡的示例

让我们来看下面的示例,以了解事件冒泡的工作原理:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Event Bubbling</title>
</head>
<body>
  <div id="p1">
    <button id="c1">I am child button</button>
  </div>

  <script>
    var parent = document.querySelector('#p1');
      parent.addEventListener('click', function(){
        console.log("Parent is invoked");
      });

   var child = document.querySelector('#c1');
      child.addEventListener('click', function(){
        console.log("Child is invoked");
      });
  </script>
</body>
</html>

输出:

JavaScript 事件冒泡和捕捉

代码解释:

  • 上面的代码是基于HTML和JavaScript的代码。
  • 我们使用了一个具有id为p1的div标签,并在其中嵌套了一个具有id为c1的按钮。
  • 现在,在JavaScript部分,我们使用querySelector()函数将html元素(p1和c1)分配给变量parent和child。
  • 然后,我们创建并包含了一个事件,即点击事件,分别给div元素和子按钮创建了两个函数,这些函数将帮助我们知道父元素和子元素执行顺序的顺序。如果先调用子元素事件,将打印”child is invoked”,否则将打印”parent is invoked”。
  • 因此,当按钮被点击时,它将首先打印”child is invoked”,这意味着子元素事件处理程序中的函数首先执行,然后转到调用div父函数。

这个顺序是由于事件冒泡的概念导致的。因此,事件冒泡就是这样发生的。

我们还可以通过下面的流程图来理解事件的流程:

JavaScript 事件冒泡和捕捉

这意味着当用户点击按钮时,点击事件从底部到顶部依次流动。

停止冒泡

从目标开始,向上移动是冒泡的过程,即从子级到父级,沿直线向上移动。但是,处理程序也可以在事件完全处理完之后决定停止冒泡。在JavaScript中,我们使用 event.stopPropagation() 方法。

例如:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Event Bubbling</title>
</head>
<body>
  <div id="p1">
    <button id="c1" onclick="event.stopPropagation()">I am child</button>
  </div>
    <script>
    var parent = document.querySelector('#p1');
      parent.addEventListener('click', function(){
        console.log("Parent is invoked");
      });
    var child = document.querySelector('#c1');
      child.addEventListener('click', function(){
        console.log("Child is invoked");
      });
  </script>
</body>
</html>

在上述的代码中,当我们点击按钮时,它不会起作用,这是因为在这里调用了event.stopPropagation()方法,导致父函数不会被调用。

JavaScript 事件冒泡和捕捉

注意:event.stopPropagation()方法仅停止事件冒泡(在一个事件上),但所有其他处理程序仍在当前元素上运行。

为了停止冒泡并阻止处理程序在当前元素上运行,我们可以使用 event.stopImmediatePropagation() 方法。这是另一种停止冒泡和执行所有其他处理程序的方法。这意味着如果一个元素在一个事件上有多个事件处理程序,使用这个event.stopImmedaitePropagation()方法将停止所有事件处理程序的冒泡。

不要不必要地使用事件冒泡

尽管事件冒泡是一种方便的方法,但建议不必要地使用它。这是因为event.stopPropagation()方法会隐藏一些潜在的问题,这些问题可能在后期导致一些问题。

让我们通过一个示例来理解:

  • 创建一个嵌套菜单,其中每个子菜单处理其元素上的点击事件,并通过调用event.stopPropagation()方法来阻止外部菜单的触发。
  • 现在为了跟踪用户在点击时的行为,我们决定捕获整个窗口的点击事件,使用document.addEventListener(‘click’)。
  • 但是由于我们调用了event.stopPropagation()方法,当点击被停止时,我们的分析将不会处理任何东西,因此我们得到了一个死区。

虽然没有了解事件捕获,事件冒泡的概念是不完整的,因此让我们从事件捕获开始,尝试结合这两个概念,完全理解概念和工作原理。

事件捕获

Netscape浏览器是第一个引入事件捕获概念的浏览器。事件捕获与事件冒泡相反,事件捕获中,事件从最外层元素向目标元素移动。而在事件冒泡的情况下,事件的移动从目标元素开始,向文件中最外层的元素移动。事件捕获在事件冒泡之前执行,但很少使用捕获,因为事件冒泡足以处理事件流。

事件捕获示例

让我们看一个示例代码来理解事件捕获的工作原理:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Event Capturing</title>
</head>
<body>
  <div id="p1">
    <button id="c1">I am Child</button>
  </div>

  <script>
    var parent = document.querySelector('#p1');
    var child = document.querySelector('#c1');

    parent.addEventListener('click', function(){
      console.log("Parent is invoked");
    },true);
    child.addEventListener('click', function(){
      console.log("Child is invoked");
    });
  </script>
</body>
</html>

输出:

JavaScript 事件冒泡和捕捉

代码解释:

  1. 上述代码基于HTML和JavaScript
  2. 在HTML部分,我们创建了一个id为p1的div。在div内部,我们嵌套并创建了一个id为c1的按钮。
  3. 在JS代码中,我们最初使用querySelector()方法将html元素即p1 id分配给变量parent,同样我们也将c1 id分配给变量child。
  4. 然后我们使用click事件并将其附加到p1 div和c1按钮上。同时包含一个在控制台上打印适当消息的函数。这意味着,如果首先调用的是子元素事件,则会首先在控制台上打印”Child is invoked”消息;而如果首先调用的是父元素事件处理程序,则会首先打印”Parent is invoked”消息。
  5. 接下来,我们在addEventListner()的第三个参数中为true,以启用在父div中进行事件捕获。
  6. 当我们单击按钮时,首先执行附加在父div中的函数。
  7. 随后,按钮的onclick()函数运行,这是由于事件捕获。由于事件捕获,父元素的事件首先执行,然后才执行目标元素的事件。

所以,当我们点击按钮时,点击事件按照以下顺序执行,如下面的流程图所示:

JavaScript 事件冒泡和捕捉

事件流程的完整概念

下图展示了事件流程的执行过程:

JavaScript 事件冒泡和捕捉

因此,事件处理和事件捕获都是事件委托的基础。这是事件流的绝对强大。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程