鼠标移动后无休止的while循环



我快疯了。我想在鼠标移动时显示一个元素,并在鼠标最后一次移动后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秒,并通过使用布尔变量来防止处理程序中代码的主要部分在此期间运行。

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,因为它更短更干净。在设置样式之前,我使用了一个变量来确保找到元素。

您需要一个mousemove范围之外的标志,该标志告诉您的侦听器您已经运行了。

if(running) return; 
running = true;

上下文:

document.addEventListener("DOMContentLoaded", function(event) {
var time = 0;
var running = false;
document.addEventListener("mousemove", function(event) {
console.log('$');
if(running) return;
running = true;
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';
}
}
});
});

这里有一种使用常规JavaScript的方法。如果您的浏览器不符合ES6,您可以用正则函数表达式替换箭头函数。这个例子在2秒后隐藏文本,而不是10秒,这样你就可以看到它的工作,而不必浪费额外的8秒。

//hide by default
document.getElementById('myBar').style.display = 'none';
var timer = null;
var hideDivTimer = () => {
timer = setTimeout(() => {
document.getElementById('myBar').style.display = 'none';
}, 2000);
};
document.addEventListener('mousemove', () => {
clearTimeout(timer);
document.getElementById('myBar').style.display = 'inline';
hideDivTimer();
});
<body>
<div id='myBar'>
<h1> TESTING </h1>
</div>
</body>

最新更新