鼠标移动后无限循环
endless while loop after mousemove
我快要疯了。
我想在鼠标移动时显示一个元素,并在最后一次移动鼠标后 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
没有暂停脚本。它会在您提供的时间安排回调,无论那个时间如何,回调 都不会 运行 直到线程中的当前 运行ning 代码完成,这永远不会发生,因为你没有增加 time
变量。
所以循环永远不会结束,所以线程永远不会可用,所以你的回调永远不会 运行,所以 time
永远不会递增。
最后,在一个事件处理程序中启动一个 setTimeout
,它共享一个局部变量并且在像 mousemove
这样的事件上非常快速地执行,很容易产生意想不到的结果。例如,在您的代码中,每次处理程序 运行 时,它都会将 time
重置为 0
,这似乎不是您想要的。
一个解决方案是放弃循环,安排 10 秒的可见性,并通过使用布尔变量防止处理程序中代码的主要部分在此期间 运行ning。
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>
我快要疯了。 我想在鼠标移动时显示一个元素,并在最后一次移动鼠标后 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
没有暂停脚本。它会在您提供的时间安排回调,无论那个时间如何,回调 都不会 运行 直到线程中的当前 运行ning 代码完成,这永远不会发生,因为你没有增加 time
变量。
所以循环永远不会结束,所以线程永远不会可用,所以你的回调永远不会 运行,所以 time
永远不会递增。
最后,在一个事件处理程序中启动一个 setTimeout
,它共享一个局部变量并且在像 mousemove
这样的事件上非常快速地执行,很容易产生意想不到的结果。例如,在您的代码中,每次处理程序 运行 时,它都会将 time
重置为 0
,这似乎不是您想要的。
一个解决方案是放弃循环,安排 10 秒的可见性,并通过使用布尔变量防止处理程序中代码的主要部分在此期间 运行ning。
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>