为什么JavaScript事件处理器被调用两次?

t1rydlwq  于 2023-03-21  发布在  Java
关注(0)|答案(2)|浏览(223)

当我向类的元素添加事件处理程序时,如下所示:

<html>

<head>
  <title>test</title>
</head>

<body>

  <div class="class1" id="div1">div1</div>

  <script>
    var divs = document.getElementsByClassName("class1");
    var onclick = function() {
      alert("clicked");
    }
    for (var i = 0; i < divs.length; i++) {
      divs[i].addEventListener("click", onclick);
    }
  </script>
</body>

</html>

如果我点击div元素,警告窗口会弹出两次。但是如果我使用下面的代码,警告窗口只会弹出一次。

<html>

<head>
  <title>test</title>
</head>

<body>
  <div class="class1" id="div1">div1</div>
  <script>
    var divs = document.getElementsByClassName("class1");
    var onclick = function() {
      alert("clicked");
    }

    divs.addEventListener("click", onclick);
  </script>
</body>

</html>

下面的代码还将弹出警报窗口两次:

<html>

<head>
  <title>test</title>
</head>

<body>

  <div class="class1" id="div1">div1</div>

  <script>
    var div = document.getElementById("div1");
    var onclick = function() {
      alert("clicked");
    }
    div.addEventListener("click", onclick);
  </script>
</body>

</html>

我想知道为什么不管我使用addEventListener("click",onclick, true);还是addEventListener("click",onclick,false);,事件处理程序都会被调用两次
我用火狐浏览器。

nwlls2ji

nwlls2ji1#

这是因为你的onclick变量是一个全局变量,这意味着当你把函数赋值给onclick时,你实际上是在这样做:

window.onclick = function () {
    alert('click');
};

因此,您将事件侦听器添加到div s,* 和 * window,当您单击div时,它将在divwindow上分别触发一次。
为了避免这种情况,可以使用Iife将变量从全局范围中屏蔽出来:

<html>

<head>
  <title>test</title>
</head>

<body>

  <div class="class1" id="div1">div1</div>

  <script>
    (function () {
        var divs = document.getElementsByClassName("class1");
        var onclick = function() {
          alert("clicked");
        }
        for (var i = 0; i < divs.length; i++) {
          divs[i].addEventListener("click", onclick);
        }
    })();
  </script>
</body>

</html>
xzlaal3s

xzlaal3s2#

为什么要循环。除了名称(你覆盖了原生的onclick)问题,为什么不只添加一次呢?你只有一个具有唯一ID的div。
使用匿名函数可以更安全地避免意外使用本机函数名

const div = document.getElementById("div1");

div.addEventListener("click", () => {
  alert("clicked");
});
<div class="class1" id="div1">div1</div>

注意:在循环中使用匿名函数时要小心,我从来不这样做,所以这里是安全的
如果您有多个元素要使用同一个事件处理程序,我总是建议委托
一个二个一个一个

相关问题