JavaScript 事件冒泡和事件捕获是什么
事件 是现代网络的基本构建。它们是一组特殊的对象,允许信号网站内发生了什么事情。通过定义事件监听器,开发人员可以在事件发生时运行特定的代码。这允许在Web应用程序上实现复杂的控制逻辑。
每当您按下键盘键、点击按钮或在手机上轻敲时,浏览器都会分派一个事件。更重要的是,您可以定义自己的事件并按您所愿分派它们!从模拟用户击键到自定义领域特定事件。
正如您可以想象的那样,了解事件的工作原理和行为对于构建强大的现代Web应用程序至关重要;同时也是熟练的Web开发人员需要掌握的一个关键概念。
示例1: 假设我们有以下HTML文档。该文档呈现一个嵌套了两个不同div的单个按钮,每个元素都和一个事件处理程序相关联,当检测到“click”事件时,该处理程序将被调用。尝试运行它,点击按钮,然后检查您的开发人员工具控制台。
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content=
"width=device-width, initial-scale=1.0">
<title>
GeeksForGeeks: What is Event
Bubbling and Capturing?
</title>
</head>
<body>
<div class="button-list"
onclick="console.log('button-list')">
<div class="button-container"
onclick="console.log('container')">
<button class="button"
onclick="console.log('button')">
Click me!
</button>
</div>
</div>
</body>
</html>
输出: 输出结果将按以下顺序显示在控制台上。
所以,发生了什么事?您点击了按钮,但仍然在控制台中打印了三个日志。有几件事情正在进行中,让我们来逐步解决。
创建事件
无论何时与DOM元素进行交互,浏览器都会创建一个新的DOM事件。在这种情况下,当点击按钮时,浏览器组合了一个特定的DOM事件:PointerEvent。 下面是它的一些属性。
{
target: button.button,
type: "click",
x: 33,
y: 9,
...
}
注意type属性被设为“click”,表示该事件代表鼠标点击(与键盘上的单次按键相对比,例如)。
分发事件
创建事件对象后,浏览器会将其分发。事件然后在DOM中遍历,这被称为 事件传播 。事件传播过程中有三个阶段。
- 捕获阶段: 事件从DOM的根部开始,沿着树向下遍历,直到找到触发事件的元素。对于遍历到的每个元素,它都会检查是否有一个设置了capture标志为true的事件监听器附加在元素上。如果没有,它就忽略它。注意在我们的示例中,控制台中首先出现的日志消息是button消息。这是因为,默认情况下,事件监听器不监听捕获阶段的事件。
-
目标阶段: 事件达到目标元素,并运行附加在目标元素上的事件监听器,如果有的话。这个阶段在我们的示例中得到了控制台中的第一个消息:“button”
-
冒泡阶段: 与捕获阶段类似,事件将遍历DOM检查事件监听器,但这次它将从触发事件的元素开始,并在DOM的根部(即html元素)结束。正是在这个阶段,我们的示例中获得了日志”container”和”button list”,因为它们是按钮最近的祖先元素,并以此顺序出现!注意,默认情况下,事件监听器将在这个阶段被调用。
监听事件
有几种方法可以监听通过DOM传递的事件。在本文的示例中,我们使用了”onclick”事件属性。这种方法监听事件简单直接,但不够灵活。最灵活、规范有效的方法是使用元素的JavaScript方法”addEventListener”。以下是它的工作原理。
要附加一个事件监听器,在元素上调用”addEventListener”,具体如下:
element.addEventListener(type, handler, useCapture);
- type :这是要监听的事件的类型,由其 type 属性定义。如前所述,在示例文档中,触发的事件的 type 值为“click”。
- handler :这是一个指向JavaScript函数的引用,在事件通过DOM(在正确的阶段)时运行。
- useCapture :这是一个布尔值,指示事件监听器应该在哪个事件传播阶段触发事件处理程序。如果设置为true,则监听器将在“捕获”阶段中调用处理程序。否则,它将在默认的“冒泡”阶段中调用。
示例2: 用另一个示例来测试。使用以下代码更新示例文档。在这里,我们删除了列表和容器的事件属性,并将两个不同的事件监听器附加到文档上:一个在捕获阶段,一个在冒泡阶段。现在打开文档并点击按钮。
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content=
"width=device-width, initial-scale=1.0">
<title>
GeeksForGeeks: What is Event
Bubbling and Capturing
</title>
</head>
<body>
<div class="button-list">
<div class="button-container">
<button class="button"
onClick="console.log('button')">
Click me!
</button>
</div>
</div>
<script>
document.addEventListener("click", () =>
console.log('Capture!'), true);
document.addEventListener("click", () =>
console.log('Bubbling!'), false);
</script>
</body>
</html>
输出: 输出将以以下顺序显示在控制台上。
如您所见,事件按照事件传播流程定义的预期顺序进行处理。
处理事件在DOM中的传播
有几个事件方法可以控制事件在DOM树中的传播。
- event.preventDefault() :阻止事件的默认浏览器行为。
- event.stopPropagation() :阻止事件在下一个元素上的传播(无论是捕获阶段中的后代还是冒泡阶段中的祖先)。
- event.stopImmediatePropagation() :类似于”event.stopPropagation()”,但也会阻止同一元素中其他监听器的传播。
结论
在本文中,我们学习了什么是事件,浏览器何时触发事件,以及事件如何通过DOM传播以被不同的事件监听器处理。现在是时候学习更多关于事件以及如何处理它们的知识了。