3

原谅我的坏标题,但现在,我什至不知道我不知道什么。

如果我有一个看起来像这样的 HTML 页面:

<html>
    <head>
        <script>
            jQuery(document).ready(function(){
                jQuery("#modalDiv").show();
                //This part takes up to a few seconds to execute and blocks the browser
                for(var i = 0; i < 10000; i++){
                    console.log("doing something");
                }
                jQuery("#modalDiv").hide();
            });
        </script>
        <style>
            #modalDiv{
                background-color:red;
                height:100px;
                width:100px;
            }
        </style>
    </head>
    <body>
        <div id="modalDiv"></div>
    </body>
</html>

ID 为“modalDiv”的元素永远不会显示在页面上。我不是想解决这个“问题”,我只是想了解幕后发生的事情导致我的脚本表现得如此。

4

4 回答 4

5

在所有同步操作完成之前,浏览器不会渲染对 DOM 的更改,并且您的代码会将控制权返回给主事件循环。这允许您对页面进行大量更改,而用户不会看到所有中间表单——它会等到您完成并只显示最终结果。

强制立即更新的一种方法是使用动画。

$(function () {
    jQuery("#modalDiv").show(5000);
    //This part takes up to a few seconds to execute and blocks the browser
    for (var i = 0; i < 10000; i++) {
        console.log("doing something");
    }
    jQuery("#modalDiv").hide(5000);
});

演示

于 2013-07-10T17:04:09.847 回答
3

一些浏览器会等到一个 javascript 线程完成执行后,才会使用对 DOM 所做的更改来更新屏幕。如果在 javascript 中对 DOM 进行了多次更改,这是一种更高效的处理方式,因为它只将内容布置一次,并且只在屏幕上显示一次。这种行为的细节将/可能因浏览器而异,因为它是一种性能优化,一旦 JS 执行完毕,它们都会得到相同的最终结果。

有一些技巧可以通过请求要求布局为最新的 DOM 属性来强制浏览器更新屏幕。您可以阅读这篇关于如何触发回流/重绘的文章: http ://www.phpied.com/rendering-repaint-reflowrelayout-restyle/和另一篇相关文章: http: //gent.ilcore.com/2011/03 /how-not-to-trigger-layout-in-webkit.html

例如,您应该能够使用此强制回流(将调用添加到.offset()):

jQuery("#modalDiv").show().offset();
//This part takes up to a few seconds to execute and blocks the browser
for(var i = 0; i < 10000; i++){
    console.log("doing something");
}
jQuery("#modalDiv").hide();

让屏幕更新可以做的另一件事是在 a 上运行您的部分代码,setTimeout()因为这可以让您的 javascript 的第一部分真正完成执行(因此屏幕将被更新)。这实际上并不像您的代码示例中那样同步运行所有内容,但有时是一个不错的解决方法。

于 2013-07-10T17:03:49.963 回答
2

您是否等待 DOM 加载?

尝试:

$(document).ready([your_function_here]);

如果文档对象模型 (DOM) 尚未加载,您将无法对其执行操作。

于 2013-07-10T16:57:35.147 回答
1

用于setTimeout(func, 0)异步运行代码(0 表示立即运行函数)因此它不会阻塞浏览器

jQuery("#modalDiv").show();

setTimeout( function() {
    //This part takes up to a few seconds to execute and blocks the browser
    for(var i = 0; i < 10000; i++){
        console.log("doing something");
    }
    jQuery("#modalDiv").hide();
}, 0);
于 2013-07-10T17:00:54.957 回答