简体   繁体   English

有没有办法从for循环中更新DOM元素?

[英]Is there a way to update DOM element from within a for loop?

I want the for loop to update <li> items along the iteration and not. 我希望for循环在迭代中更新<li>项而不是。 after it. 在它之后。

Here is the complete code: 这是完整的代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <div class="for">
        <ul id="unordered-list">

        </ul>
    </div>

    <script>
        const parentUL = document.querySelector('#unordered-list');
        for (let i = 0; i < 100000; i++) {
            const li = document.createElement('li');
            li.innerHTML = i;
            parentUL.appendChild(li);
        }</script>
</body>

</html>

I expect the <li> to be updated while the for loop is running, in the current case, all of them appear after the loop has finished running. 我希望在for循环运行时更新<li> ,在当前情况下,所有这些都在循环运行完毕后出现。

The "problem" which arises here, is that ECMAscript is a single-threaded process. 这里出现的“问题”是ECMAscript是一个单线程进程。 In most cases, ECMAscript code runs within the such called "UI Thread". 在大多数情况下,ECMAscript代码在所谓的“UI线程”内运行。 As you already might have guessed by the name, other processes, like updating and visualising DOM components (including CSS changes), are also running in this very process. 正如您可能已经猜到的那样,其他流程(如更新和可视化DOM组件(包括CSS更改))也在此过程中运行。 Now, without going into greater detail, what happens here basically looks like: 现在,在没有详细说明的情况下,这里发生的事情基本上如下:

[ HTML:DOM Rendered - UI UPDATE - JS:LOOP(100000) - UI UPDATE ]

Since your entire loop runs synchronously, there is no chance for the UI Thread to show any rendered updates. 由于整个循环同步运行,因此UI线程无法显示任何呈现的更新。 Your only chance to achieve that is to manually interrupt your loop from time to time. 实现这一目标的唯一机会是不时手动中断循环。 There are several ways to do this, the most simple one is probably the use of setTimeout() . 有几种方法可以做到这一点,最简单的方法可能是使用setTimeout()

You could re-write your code into: 您可以将代码重新编写为:

let i = 0;
(function loop() {
    const li = document.createElement('li');
    li.innerHTML = i++;
    parentUL.appendChild(li);

    if( i < 100000 ) {
        setTimeout(loop, 20);
    }
}());

What happens now, is that the execution of your JS code gets interrupted every 20 milliseconds and the UI Thread can update whatever visual changes are necessary. 现在发生的事情是,你的JS代码的执行每20毫秒被中断,UI线程可以更新任何必要的视觉变化。

[ HTML:DOM Rendered - UI UPDATE - loop() - UI UPDATE - loop() - UI UPDATE - ... ]

although 100000 is a high number such for/loop doesn't take longer den some milliseconds. 虽然100000是一个很高的数字,这样的/ loop不需要花费几毫秒的时间。 And due to better performance and user experience, browsers optimize refresh rate for such changes. 由于更好的性能和用户体验,浏览器可以优化这些更改的刷新率。 If you want to have a visible time difference between each append, you may add timeout like this: 如果你想在每个追加之间有一个可见的时差,你可以像这样添加超时:

const parentUL = document.querySelector('#unordered-list');
    for (let i = 0; i < 100000; i++) {
        const li = document.createElement('li');
        li.innerHTML = i;
        setTimeout(()=>{    
            parentUL.appendChild(li);},i * 250);
        })
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM