整个脚本完成后,为什么Javascript呈现更改为DOM?

时间:2018-11-09 06:22:46

标签: javascript

<!DOCTYPE html>
<html>
<head>
</head>

<body>    
    <ul>
        <li>Skittles</li>
        <li>Starburst</li>
        <li>Twix</li>
    </ul>

    <script type="text/javascript">

        function timeDiff(n){
            var start = now = Date.now();

            while(now - start < n*1000){
                now = Date.now();
            }
        }


        var lis = document.getElementsByTagName("li");

        lis[0].textContent = "Text 1";
        timeDiff(2);
        lis[1].textContent = "Text 2";
        timeDiff(2);
        lis[2].textContent = "Text 3";
        timeDiff(2);
    </script>
</body>
</html>

运行上面的代码时,程序将等待6秒钟,然后一起更改所有三个li的文本。

如果我在控制台中运行以下javascript:

console.log("Text 1");
timeDiff(2);
console.log("Text 2");
timeDiff(2);
console.log("Text 3");
timeDiff(2);

然后,控制台将打印“文本1”,等待2秒,然后打印“文本2”,等待2秒,然后打印“文本3”。

为什么两种情况下Javascript的行为都不一样?在第一种情况下,它是一起操纵li的,而在第二种情况下,它是在控制台上一个接一个地打印。

2 个答案:

答案 0 :(得分:1)

第一个示例中的代码问题是您正在做的事情称为忙等待。在javascript完成执行后,浏览器会更新页面显示的html。该脚本将在6秒钟后完成执行,这就是您看到列表项更改的时间。如果您希望经过一定时间后在javascript中发生某些事情,则应使用setTimeout

答案 1 :(得分:1)

在JavaScript返回主事件循环之前,浏览器不会将更改呈现给DOM。这样,脚本就可以对页面进行大量更改,并且用户看不到所有中间步骤,而只能看到最终结果。

在控制台中执行语句时,它会在每个语句之后返回到主事件循环,因此您可以看到更改的结果。但是,当您运行脚本时,在整个脚本完成之前不会呈现任何内容。

使用while来延迟操作,而不是setTimeout循环。在等待超时完成时,这不会阻止浏览器。

var lis = document.getElementsByTagName("li");

setTimeout(() => {
  lis[0].textContent = "Text 1";
  setTimeout(() => {
    lis[1].textContent = "Text 2";
    setTimeout(() => {
      lis[2].textContent = "Text 3";
    }, 2000);
  }, 2000);
}, 2000);
<ul>
  <li>Skittles</li>
  <li>Starburst</li>
  <li>Twix</li>
</ul>