javascript div更新率

时间:2017-04-13 07:17:30

标签: javascript html

我有一个非常简单的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>

6 个答案:

答案 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)。

最后,新语言关键字asyncawait可以让您的代码更轻松。您可以保持循环并抽象等待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 setIntervalclearinterval

&#13;
&#13;
<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;
&#13;
&#13;

答案 4 :(得分:0)

您的for循环在milliseconds中执行,您只获得循环的最后一个值。如果您想实时使用setInterval

&#13;
&#13;
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;
&#13;
&#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>