我快要疯了。 我想在鼠标移动时显示一个元素,并在鼠标最后一次移动 10 秒后隐藏它。
我写的是:
document.addEventListener("DOMContentLoaded", function(event) {
var time = 0;
document.addEventListener("mousemove", function(event) {
console.log('$');
document.getElementsByClassName("mybar")[0].style.visibility = 'visible';
time = 0;
while (time < 11) {
setTimeout(function() {
time++
}, 1000);
console.log(time, time == 10);
if (time == 10) {
document.getElementsByClassName("mybar")[0].style.visibility = 'hidden';
}
}
});
});
<div class='mybar'>
<h1> TESTING </h1>
</div>
为什么会陷入无限循环? 为什么不按条件退出?为什么 if 永远得不到“true”参数? 注意:不要以这种方式运行......它会杀死你的标签。
最佳答案
首先,您不需要等待 DOMContentLoaded
来将事件监听器添加到 document
,因为如果您这样做了,您首先就无法添加 DOMContentLoaded
。
无限循环是因为 setTimeout
没有暂停脚本。它会按照您提供的时间安排其回调,并且无论该时间如何,回调都不会运行,直到线程中当前运行的代码完成为止,这种情况永远不会发生,因为您没有增加 time
变量.
因此循环永远不会结束,因此线程永远不可用,因此您的回调永远无法运行,因此 time
永远不会递增。
最后,在共享局部变量的事件处理程序中启动 setTimeout
并在像 mousemove
这样的事件上非常快速地执行很容易产生意外结果。例如,在您的代码中,每次处理程序运行时,它都会将 time
重置为 0
,这似乎不是您想要的。
解决方案是放弃循环,将可见性安排为 10 秒,并使用 bool 变量阻止处理程序中代码的主要部分同时运行。
var timer = null;
document.addEventListener("mousemove", function(event) {
var myBar = document.querySelector(".mybar");
if (!myBar) {
return; // there's no mybar element
}
if (timer == null) {
myBar.style.visibility = 'visible';
} else {
clearTimeout(timer); // clear the currently running timer
}
// set to hidden in 10 seconds
timer = setTimeout(function() {
myBar.style.visibility = 'hidden';
timer = null; // clear the timer
}, 10000);
});
我还切换到 querySelector
而不是 getElementsByClassName
,因为它更短、更干净。我使用了一个变量来确保在设置样式之前找到该元素。
关于javascript - 鼠标移动后无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46834694/