我有一个非常简单的HTML / Javascript,如下所示 但是当我运行它时,标签只更新一次,当它是99999时,这不是我想要的行为。我希望标签能够“实时”更新。有什么方法可以强迫它重绘。我试图将它放入
notice.style.display = 'none';
notice.innerHTML = i
notice.style.display = 'block';
但它仍然无效。 非常感谢你。
<html>
<head>
</head>
<body>
<label id = "esperanto-notice"></label>
<script type="text/javascript">
var notice = document.getElementById("esperanto-notice")
for(var i =0; i<100000; i++){
notice.innerHTML = i
console.log(i)
}
console.log("done")
</script>
</body>
</html>
答案 0 :(得分:2)
你的循环工作速度非常快,你无法实时看到变化。要达到目标,您应该在增量计数器之前进行一些超时。例如:
<html>
<head>
</head>
<body>
<label id = "esperanto-notice"></label>
<script type="text/javascript">
var notice = document.getElementById("esperanto-notice")
var i = 0;
var interval = setInterval(function() {
notice.innerHTML = ++i;
if (i === 100000)
clearInterval(interval)
}, 500);
</script>
</body>
</html>
答案 1 :(得分:2)
Javascript尝试在更新DOM之前运行其所有内联代码,因为后者很慢。整个循环在页面更新一次之前运行。
我们可以强制页面更新:
for(var i =0; i<100000; i++){
notice.innerHTML = i;
notice.getBoundingClientRect(); // Force DOM update to get latest size
console.log(i);
}
然而,当DOM正在更新时,它仍然会直接返回到JS以继续运行循环 - 这比您看到的更快,并且仍然似乎挂起。
您需要做的是暂停JS执行,以便页面有机会更新。
我们可以使用异步JS函数执行此操作 - 完成当前JS块但会将一个回调函数排队以稍后触发(在这种情况下,在用户看到它之后):
var notice = document.getElementById("esperanto-notice");
var i = 0;
// Function to write the next value, increment, and queue up the next timeout
var nextFunc = function() {
console.log(i);
notice.innerHTML = i++;
if (i < 100000)
setTimeout(nextFunc, 16); // 16ms is 60FPS
else
console.log('done');
}
// Start it off
nextFunc();
<label id="esperanto-notice"></label>
现在整个JS运行并且nextFunc
执行一次。它还会将它排队等待16ms后再次触发,但在此之前它会让浏览器更新页面。
每次nextFunc
触发它都会使用setTimeout
排队下一次执行,然后页面有一个要更新的帧(让用户看到它),然后再次触发。
现代浏览器提供专门用于等待下一帧的功能:requestAnimationFrame
:
var notice = document.getElementById("esperanto-notice");
var i = 0;
// Function to write the next value, increment, and queue up the next timeout
var nextFunc = function() {
console.log(i);
notice.innerHTML = i++;
if (i < 100000)
// Request the next visible frame to continue
requestAnimationFrame(nextFunc);
else
console.log('done');
}
// Start it off
nextFunc();
<label id="esperanto-notice"></label>
这是最好的方法,除非您需要支持旧版本的IE(&lt; = 9),因为requestAnimationFrame
可以处理任何帧的持续时间(setTimeout
如果你有很多JANK)。
最后,新语言关键字async
和await
可以让您的代码更轻松。您可以保持循环并抽象等待DOM更新。下一个代码段仅在Chrome和FX等现代浏览器上运行(但可以使用Babel或TypeScript来支持IE):
(async function() {
var notice = document.getElementById("esperanto-notice");
for (var i = 0; i < 100000; i++) {
console.log(i);
notice.innerHTML = i;
// Pass back to the DOM until the next frame
await new Promise(r => requestAnimationFrame(r));
}
console.log('done');
})();
<label id="esperanto-notice"></label>
答案 2 :(得分:0)
基本上更新发生得非常快,你只看到该div的最终更新,
尝试将for循环更改为以下以查看更改
for(var i =0; i<100000; i++)
{
(function(i){ //wrapping the value of i in an IIFE so that it can be locked
setTimeout( function(){
notice.innerHTML = i
console.log(i)
} , i * 100); //i*100 is in milliseconds
})(i);
}
答案 3 :(得分:0)
使用javascript setInterval和clearinterval。
<html>
<body>
<label id="esperanto-notice"></label>
<script type="text/javascript">
var notice = document.getElementById("esperanto-notice");
var i = 0;
var interval = setInterval(function () {
notice.innerHTML = i;
i++;
if(i >= 100000) {
clearInterval(interval);
}
}, 100);
</script>
</body>
</html>
&#13;
答案 4 :(得分:0)
您的for
循环在milliseconds
中执行,您只获得循环的最后一个值。如果您想实时使用setInterval
var notice = document.getElementById("esperanto-notice")
var i = 0
var refreshIntervalId = setInterval(changeCounter,1000)
function changeCounter(){
i++
notice.innerHTML = i
if(i==10){
clearInterval(refreshIntervalId)
console.log("done")
}
}
&#13;
<html>
<body>
<label id = "esperanto-notice"></label>
</body>
</html>
&#13;
答案 5 :(得分:0)
由于您的代码实际上在“实时”中运行得非常快,因此您无法在屏幕上看到数字更改。为了做到这一点,你需要让数字变得足够慢,以便你注意到。为此,您可以setTimeout并延迟更新到DOM。
var notice = document.getElementById("esperanto-notice")
for (var i = 0; i < 100000; i++) {
setTimeout(function(innerI) {
notice.innerHTML = innerI;
console.log(innerI);
}.bind(null, i), i * 100);
}
console.log("done")
<html>
<head>
</head>
<body>
<label id="esperanto-notice"></label>
</body>
</html>