我期望的是,当我点击按钮 4 时,事件监听器应该立即从按钮 1 中删除,但实际上是什么发生的情况是,事件监听器仅在单击按钮 1 一次后停止。
var btn = document.querySelector('.container').children;
for (let x = 0; x < btn.length; x++) {
btn[x].addEventListener('click', changeFontSize);
function changeFontSize() {
// changing the font sizes from 16 to 20 , or the opposite.
if (getComputedStyle(btn[x]).fontSize == '16px') {
btn[x].style.fontSize = '20px';
} else {
btn[x].style.fontSize = '16px';
}
// nesting a function to remove the event listener form btn0 after btn4 gets clicked on
if (getComputedStyle(btn[3]).fontSize == '20px') {
btn[0].removeEventListener('click', changeFontSize);
}
}
}
button {
font-size: 1em;
}
<div class="container">
<button id='btn'>btn 1</button>
<button id='btn'>btn 2</button>
<button id='btn'>btn 3</button>
<button id='btn'>btn 4</button>
<button id='btn'>btn 1</button>
</div>
最佳答案
当执行按钮 4 的事件监听器删除时,它会尝试在按钮 1 的闭包中删除其对 function changeFontSize()
的引用。此操作失败,因为按钮 1 没有按钮 4 的引用处理程序附加到它。点击按钮4后,可能会处于其fontSize == "20px"
为true的状态。下次您在按钮 4 处于这种状态下单击按钮 1 时,按钮 1 会成功删除其自己的监听器,但前提是最后一次更改其字体大小。
此外,当按钮 4 处于 fontSize == "20px"
状态时,单击时,所有其他按钮中的 if
都会徒劳地尝试从按钮 0 中删除其监听器.
问题的最小重现:
const [foo, bar] = document.querySelectorAll("button");
let barClicked = false;
function fooClickHandler () {
console.log("foo clicked");
if (barClicked) {
foo.removeEventListener("click", fooClickHandler);
console.log("foo listener removed");
}
}
function barClickHandler () {
console.log("bar clicked");
barClicked = true;
foo.removeEventListener("click", barClickHandler); // does nothing
}
foo.addEventListener("click", fooClickHandler);
bar.addEventListener("click", barClickHandler);
<button>foo</button>
<button>bar</button>
您可以将事件处理程序回调函数存储在专门用于按钮 1 的变量中,并确保按钮 4 的处理程序准确删除按钮 1 的处理程序函数。但整体设计看起来相当脆弱,因此我建议重新考虑,具体取决于您的应用程序上下文。
顺便说一句,我不确定 CSS 中的 1em 是否能保证您的初始 16px 大小。如果您期望的话,我会在 CSS 中将其明确设置为 16px。将这些大小硬编码到 JS 中有点代码味道。
Id 在整个 DOM 中必须是唯一的,但这里不是这样的。
顺便说一句,始终使用 ===
而不是 ==
和 const
/let
而不是一般来说,var
,尽管这不是这里的错误。
关于javascript - 为什么函数执行后事件监听器不立即被删除?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66728712/