JavaScript,点击按钮会触发父级事件监听器

3

我的页面上有两个按钮,我用它们来尝试新的东西。两个按钮都使用“onclick”链接到不同的JS函数。 由于某种原因,第二个按钮同时激活了两个函数?我无法弄清楚自己做错了什么。

HTML 如下:

<!DOCTYPE html>
<html>
    <head>
        <link HREF="styleTest.css" rel="stylesheet">

        <link rel="preconnect" href="https://fonts.googleapis.com">
        <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
        <link href="https://fonts.googleapis.com/css2?family=Roboto+Serif:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet">
    
        <script type="text/javascript" src="script.js"></script>

        <title>TEST</title>

    </head>

    <body>
        <div class="page">


        <div class="nav-container" onclick="hamburger(this)">
            
            <div class="ham-container">
                <div class="hamburger-1"></div>
                <div class="hamburger-2"></div>
                <div class="hamburger-3"></div>
            </div> 

            <div class="nav-bar">
                <a>Home</a>     
                <a>Services</a>     
                <a>About</a>    
                <a>Projects</a>
            </div>



            <div class="button-test">
                <button onclick="clickTest()">CLICK ME</button>
                <h1>Test text</h1>
            </div>

        </div>


    </body>

而这两个JS函数:

function hamburger(x) {
    x.classList.toggle("change");
  }

var i =0

function clickTest() {
  i++;
  console.log(i)
}

我做错了什么?


4
事件会向上冒泡,如果不想让它们冒泡,就需要手动取消事件。 - Samathingamajig
1
阅读MDN上有关事件的文章。此文 - Emiel Zuurbier
1
调用 clickTest 函数的按钮是嵌套在调用 hamburger 函数的 div 中的。这就是为什么它们都被调用的原因。 - Abir Taheer
2
我也强烈建议学习addEventListener方法,而不是过时的内联事件处理程序 - Emiel Zuurbier
@EmielZuurbier 谢谢!这帮助我解决了问题并学到了新东西。 - Thomas Doll-Datema
@ThomasDoll-Datema 似乎是一个新的并且不相关的问题。请为此打开一个新的问题。 - Emiel Zuurbier
3个回答

2
当您在元素上触发事件时,它将按顺序为其父元素,祖父元素......一直到最后一个父元素触发。通常我们不会看到这种行为发生,因为通常我们在元素的家族中只有一个事件侦听器。
但是,如果触发的元素位于具有相同事件的父元素内,例如在您的情况下,两者都将被触发。但是,您可以通过使用stopPropagation方法来防止此行为,方式如下:
function clickTest(e) {
  e.stopPropagation();
  i++;
  console.log(i)
}

1

事件监听器的工作方式是,当您有一个嵌套对象(例如在 div 中的 button),并且它们都具有事件监听器时,当单击内部元素(按钮)时,button 的事件监听器将先于父级事件监听器触发。

要解决这个问题,您需要使用以下代码停止事件传播。

<button onclick="clickTest(event)">CLICK ME</button>

而且这个脚本

  function clickTest(e) {
  e.stopPropagation();
  i++;
  console.log(i)
}

1
这是由于DOM中的“冒泡”概念导致的。
当元素发生事件时,它首先运行其自身的处理程序,然后在其父级上运行,再一直向上运行到其他祖先元素。

Try playing around with this snippet below .

<style>
  body * {
    margin: 10px;
    border: 1px solid blue;
  }
</style>

<form onclick="alert('form')">FORM
  <div onclick="alert('div')">DIV
    <p onclick="alert('p')">P</p>
  </div>
</form>

点击内部的 <p> 会先触发它自己的 onclick:

然后是外层的 <div>

接着是外层的 <form>

一直往上直到文档对象。

请参考此页面以获得更多清晰的说明:链接


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接