JavaScript 事件冒泡与事件捕获是什么

JavaScript 事件冒泡与事件捕获是什么

事件冒泡和事件捕获是JavaScript中两个有趣的概念。在深入了解这些令人着迷的概念之前,首先让我们了解一下什么是事件监听器?事件监听器基本上是一个等待事件发生的函数。该事件可以是任何事件,比如鼠标点击事件、提交表单、按键等。

事件监听器包含三个参数,并且可以使用以下语法进行定义。

<element>.addEventListener(<eventName>, 
<callbackFunction>, {capture : boolean});
JavaScript
  • <element>:附加事件监听器的元素。
  • <eventName>:可以是‘click’、‘key up’、‘key down’等事件。
  • <callbackFunction>:事件发生之后触发的函数。
  • {capture: boolean}:它告诉事件是在捕获阶段还是冒泡阶段发生的(可选)。

示例 1: 让我们以一个示例来理解事件冒泡和事件捕获。

HTML

<!DOCTYPE html>
<html>
 
<head>
    <script src=
"https://code.jquery.com/jquery-3.6.0.min.js">
    </script>
    <style>
        div {
            color: white;
            display: flex;
            justify-content: center;
            align-items: center;
            flex-direction: column;
        }
        h2 {
            color: black;
        }
        #grandparent {
            background-color: green;
            width: 300px;
            height: 300px;
        }
        #parent {
            background-color: blue;
            width: 200px;
            height: 200px;
        }
        #child {
            background-color: red;
            width: 100px;
            height: 100px;
        }
    </style>
</head>
 
<body>
    <div>
        <h2>Welcome To GFG</h2>
        <div id="grandparent">GrandParent
            <div id="parent">Parent
                <div id="child">Child</div>
            </div>
        </div>
    </div>
 
    <script>
        const grandParent = document.getElementById("grandparent");
        const parent = document.getElementById("parent");
        const child = document.getElementById("child");
 
        grandParent.addEventListener("click", (e) => {
            console.log("GrandParent");
        }, { capture: false });
        parent.addEventListener("click", (e) => {
            console.log("Parent");
        }, { capture: false });
        child.addEventListener("click", (e) => {
            console.log("Child");
        }, { capture: false });
    </script>
</body>
</html>
JavaScript

输出:

JavaScript 事件冒泡与事件捕获是什么

当我们点击具有子级为其id的div时,我们应该在控制台上得到输出为’child’。但是出乎意料的是,即使我们没有点击具有父级和祖父级作为其id的div,我们也收到了不同的输出。这涉及到事件冒泡的概念。子级div既存在于父级div中,也存在于祖父级div中。因此,当点击子级div时,我们间接点击了父级div和祖父级div。因此,传播是从内部向外部在DOM中移动,或者我们可以说事件正在冒泡。

因此,在DOM中从最近的元素到最远的元素传播的过程被称为事件冒泡。

示例2: 在上面的示例中,让我们改变 addEventListener() 的第三个参数的值,并看看输出会发生什么变化。

HTML

<!DOCTYPE html>
<html>
<head>
    
    <style>
        div {
            color: white;
            display: flex;
            justify-content: center;
            align-items: center;
            flex-direction: column;
        }
        h2 {
            color: black;
        }
        #grandparent {
            background-color: green;
            width: 300px;
            height: 300px;
        }
        #parent {
            background-color: blue;
            width: 200px;
            height: 200px;
        }
        #child {
            background-color: red;
            width: 100px;
            height: 100px;
        }
    </style>
</head>
 
<body>
    <div>
        <h2>Welcome To GFG</h2>
        <div id="grandparent">GrandParent
            <div id="parent">Parent
                <div id="child"> Child</div>
            </div>
        </div>
    </div>
    <script>
        const grandParent = document.getElementById("grandparent");
        const parent = document.getElementById("parent");
        const child = document.getElementById("child");
         
        // Changing value of capture parameter as 'true'
        grandParent.addEventListener("click", (e) => {
            console.log("GrandParent");
        }, { capture: true });
        parent.addEventListener("click", (e) => {
            console.log("Parent");
        }, { capture: true });
        child.addEventListener("click", (e) => {
            console.log("Child");
        }, { capture: true });
    </script>
</body>
 
</html>
JavaScript

JavaScript 事件冒泡与事件捕获是什么

很明显,子div的祖先div首先被打印,然后才是子div本身。因此,在DOM中从最远的元素向最近的元素传播的过程被称为事件捕获 这两个术语正好相反。

示例3: 让我们在代码中进一步尝试以获得更好的理解。

HTML

<!DOCTYPE html>
<html>
 
<head>   
    <style>
        div {
            color: white;
            display: flex;
            justify-content: center;
            align-items: center;
            flex-direction: column;
        }
        h2 {
            color: black;
        }
        #grandparent {
            background-color: green;
            width: 300px;
            height: 300px;
        }
        #parent {
            background-color: blue;
            width: 200px;
            height: 200px;
        }
        #child {
            background-color: red;
            width: 100px;
            height: 100px;
        }
    </style>
</head>
 
<body>
    <div>
        <h2>Welcome To GFG</h2>
        <div id="grandparent">GrandParent
            <div id="parent">Parent
                <div id="child"> Child</div>
            </div>
        </div>
    </div>
 
    <script>
        const grandParent = document.getElementById("grandparent");
        const parent = document.getElementById("parent");
        const child = document.getElementById("child");
         
        document.addEventListener("click", (e) => {
            console.log("Document capturing");
        }, { capture: true });
         
        grandParent.addEventListener("click", (e) => {
            console.log("GrandParent capturing");
        }, { capture: true });
         
        parent.addEventListener("click", (e) => {
            console.log("Parent capturing");
        }, { capture: true });
         
        child.addEventListener("click", (e) => {
            console.log("Child capturing");
        }, { capture: true });
          document.addEventListener("click", (e) => {
            console.log("Document bubbling");
        }, { capture: false });
         
        grandParent.addEventListener("click", (e) => {
            console.log("GrandParent bubbling");
        }, { capture: false });
         
        parent.addEventListener("click", (e) => {
            console.log("Parent bubbling");
        }, { capture: false });
         
        child.addEventListener("click", (e) => {
            console.log("Child bubbling");
        }, { capture: false });
    </script>
</body>
 
</html>
JavaScript

输出: 如果我们点击了带有id为child的div,那么这将是输出。

JavaScript 事件冒泡与事件捕获是什么

我们可以看到事件监听器的事件捕获先发生,然后再发生事件冒泡。这意味着事件监听器的传播首先是从外到内,然后是从内到外在DOM中。

如何停止事件冒泡和事件捕获?

在上面的示例中,我们可以看到在addEventListener()的回调函数中有一个参数“e”(有时称为“event”)。当我们为元素添加事件监听器时,它是自动定义的一个事件对象。这个对象’e’有一个名为stopPropagation()的函数,它可以帮助我们防止这种烦人的行为。

示例4: 让我们看看在下面的代码中点击child div时会发生什么。

HTML

<!DOCTYPE html>
<html>
 
<head>
    <style>
        div {
            color: white;
            display: flex;
            justify-content: center;
            align-items: center;
            flex-direction: column;
        }
        h2 {
            color: black;
        }
        #grandparent {
            background-color: green;
            width: 300px;
            height: 300px;
        }
        #parent {
            background-color: blue;
            width: 200px;
            height: 200px;
        }
        #child {
            background-color: red;
            width: 100px;
            height: 100px;
        }
    </style>
</head>
 
<body>
    <div>
        <h2>Welcome To GFG</h2>
        <div id="grandparent">GrandParent
            <div id="parent">Parent
                <div id="child"> Child</div>
            </div>
        </div>
    </div>
 
    <script>
        const grandParent = document.getElementById("grandparent");
        const parent = document.getElementById("parent");
        const child = document.getElementById("child");
        grandParent.addEventListener("click", (e) => {
            console.log("GrandParent bubbling");
        });
        parent.addEventListener("click", (e) => {
            e.stopPropagation();  //syntax to stop event bubbling
            console.log("Parent bubbling");
        });
        child.addEventListener("click", (e) => {
            console.log("Child bubbling");
        });
    </script>
</body>
 
</html>
JavaScript

输出:

JavaScript 事件冒泡与事件捕获是什么

如果我们点击了子div,事件传播会停止在父div上,并且不会传递到祖父div。因此,事件冒泡被阻止了。

注意: 使用相同的方法也可以阻止事件捕获。

需要记住的重要要点:

  • 如果我们在 addEventListener() 中没有指定第三个参数,默认情况下会发生事件冒泡。
  • 事件冒泡和事件捕获仅当元素及其所有祖先元素都被附加了相同的事件监听器时(在我们的示例中为’click’事件)。

    结论: 我们学习了事件冒泡和事件捕获,并且这些是一些关键要点。

  • 事件捕获意味着事件从祖先元素传播到子元素,而事件冒泡意味着事件从子元素传播到祖先元素。

  • 事件捕获发生在事件冒泡之后。
  • 如果{capture:true},则会发生事件捕获,否则会发生事件冒泡。
  • 可以使用 stopPropagation() 方法来防止两者发生。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程

登录

注册