为什么 Javascript 事件处理程序被调用两次?
Why Javascript event handler is called twice?
当我将事件处理程序添加到 class 的元素时,如下所示:
<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 元素,警告 window 会弹出两次。但是如果我使用下面的代码,警告 window 只会弹出一次。
<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>
下面的代码也会弹出alertwindow两次:
<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);
我用火狐浏览器
发生这种情况是因为您的 onclick
变量是一个全局变量,这意味着当您将函数分配给 onclick
:
时,您实际上是在执行此操作
window.onclick = function () {
alert('click');
};
因此,您将事件侦听器添加到 div
、 和 window
,当您单击 div
时,它在 div
开火一次,在 window
.
开火一次
为避免这种情况,请使用 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>
为什么要循环。除了名称(您覆盖本机 onclick)问题之外,为什么不只添加一次?您只有一个 div 具有唯一 ID。
使用匿名函数可以更安全地避免意外使用本机函数名称
const div = document.getElementById("div1");
div.addEventListener("click", () => {
alert("clicked");
});
<div class="class1" id="div1">div1</div>
如果您有多个元素使用同一个事件处理程序,委托
document.getElementById("container").addEventListener("click", (e) => {
const div = e.target.closest("div");
if (div && div.classList.contains("class1")) {
alert(div.id + " clicked");
}
});
<div id="container">
<div class="class1" id="div1">div1</div>
<div class="class1" id="div2">div2</div>
</div>
当我将事件处理程序添加到 class 的元素时,如下所示:
<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 元素,警告 window 会弹出两次。但是如果我使用下面的代码,警告 window 只会弹出一次。
<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>
下面的代码也会弹出alertwindow两次:
<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);
我用火狐浏览器
发生这种情况是因为您的 onclick
变量是一个全局变量,这意味着当您将函数分配给 onclick
:
window.onclick = function () {
alert('click');
};
因此,您将事件侦听器添加到 div
、 和 window
,当您单击 div
时,它在 div
开火一次,在 window
.
为避免这种情况,请使用 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>
为什么要循环。除了名称(您覆盖本机 onclick)问题之外,为什么不只添加一次?您只有一个 div 具有唯一 ID。
使用匿名函数可以更安全地避免意外使用本机函数名称
const div = document.getElementById("div1");
div.addEventListener("click", () => {
alert("clicked");
});
<div class="class1" id="div1">div1</div>
如果您有多个元素使用同一个事件处理程序,委托
document.getElementById("container").addEventListener("click", (e) => {
const div = e.target.closest("div");
if (div && div.classList.contains("class1")) {
alert(div.id + " clicked");
}
});
<div id="container">
<div class="class1" id="div1">div1</div>
<div class="class1" id="div2">div2</div>
</div>