Window.onload 会阻塞 DOM 渲染,而 setTimeout 不会

发布于 2025-01-15 12:52:32 字数 887 浏览 0 评论 0原文

我已经在 chrome 和 safari 中对此进行了测试,两者都有相同的结果。

当我尝试在 window onload 事件之后运行循环时,它会一直等待循环结束,然后再渲染其上方的常规 DOM。

但是,如果我通过 setTimeout 调用循环代码,即使它是 0 毫秒,它也会加载 DOM 然后运行循环。

窗口 onload 事件不应该默认执行此操作吗?我想了解如何才能真正让 javascript 代码在 DOM 渲染后运行。

谢谢。

<!DOCTYPE html>
<html lang="en">
<body>
    <div id="root">
        foo
    </div>

    <script>

        window.onload = ( () => {
            // b()
            setTimeout(() => {
                b()
            }, 0);
        });

        function b() {

            let i = 0
            while (i < 400000000) {
                i++
            }
            document.getElementById('root').innerHTML = i

        }

    </script>
</body>

</html>

但是,如果我们注释掉 setTimeout 中的 b() 并取消注释上面的 b(),它将等到 b() 完成后再渲染 DOM。

谢谢。

I have tested this in chrome and safari, both having same result.

When i try to run a loop after window onload event, it keeps waiting for the loop to end before rendering the regular DOM above it.

However, if i call the loop code through a setTimeout, even if it's of 0 millisecond, it loads the DOM and then runs the loop.

Shouldn't window onload event do this by default? I want to understand how can we truly make the javascript code run after the DOM is rendered.

Thanks.

<!DOCTYPE html>
<html lang="en">
<body>
    <div id="root">
        foo
    </div>

    <script>

        window.onload = ( () => {
            // b()
            setTimeout(() => {
                b()
            }, 0);
        });

        function b() {

            let i = 0
            while (i < 400000000) {
                i++
            }
            document.getElementById('root').innerHTML = i

        }

    </script>
</body>

</html>

However if we comment out the b() inside setTimeout and uncomment the b() above it, it will wait till b() finishes before rendering the DOM.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

向地狱狂奔 2025-01-22 12:52:32

当所有资源都已加载时,将触发 onload 事件。这里没有要加载的外部资源,因此它将在下一个绘画帧之前立即触发。

超时可能会让浏览器更新渲染,但这不是给定的,下一次绘制可能会在超时后发生。

如果您想确保在执行脚本之前页面至少已绘制一次,请通过调用 requestAnimationFrame() 等待下一个绘制帧,并在回调中等待下一个任务(例如,使用setTimeout(fn, 0)):

requestAnimationFrame(() => setTimeout(yourScript, 0));

The onload event fires when all the resources have been loaded. Here there is no external resource to load, so it will fire instantly, before the next painting frame.

The timeout may let the browser update the rendering, but it's not a given, the next painting could happen after the timeout.

If you want to ensure the page has been painted at least once before executing your script, then wait for the next painting frame, by calling requestAnimationFrame() and in the callback wait just the next task (e.g with setTimeout(fn, 0)):

requestAnimationFrame(() => setTimeout(yourScript, 0));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文