什么是关于DOM树解析和渲染树的$(document).ready?

时间:2014-07-15 06:19:12

标签: javascript jquery html dom

据我所知:

    当整个html 已解析 时会触发
  • $(document).ready()
  • 脚本(内联或外部)解析树阻止

但令我惊讶的是,以下作品意外

<html>
<head>
</head>
<body>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <h1>This should show !</h1>
    <script>
            $(document).ready(function() {
                // Intentional infinite loop
                for(var i=0; i<100; i++) {
                    i--;
                }
            });
    </script>
    <h1>This should *not* show !</h1>
</body>
</html>

执行上述操作后,它会进入无限循环并显示空白屏幕。

在进入无限循环之前,预计会在屏幕上看到这应该显示!

更新

UPDATE2

  • 请提供引文
  • AFAIK HTML可以部分呈现并仅在css上呈现块,这里没有使用(评论?)

UPDATE3

  • 换句话说,JS在循环中被阻止,但是什么阻止了部分DOM的渲染(已经解析过了)?
  • HTML以递增方式呈现,为什么不在这种情况下?

发生了什么?

4 个答案:

答案 0 :(得分:0)

如果您阅读jQuery文档已准备就绪,您应该记下In most cases, the script can be run as soon as the DOM hierarchy has been fully constructed.行。我从这一行中得到的结论是,这并不一定意味着页面会显示。因此,即使您没有任何css代码,也不意味着您的文档会显示。

以下是StackOverflow问题的链接,可以很好地解释这一点:window.onload vs $(document).ready()

以下是指向整个页面呈现过程的页面的链接:http://friendlybit.com/css/rendering-a-web-page-step-by-step/

如果您注意到上述链接中的步骤18,那么在所有HTML&amp;加载CSS,并在执行Javascript后,实际打印页面。以下StackOverflow问题包含了进一步说明这一点的良好链接:Describe the page rendering process in a browser?

进一步澄清(对更新3的回应):

这是我对friendlybit文章的总结:

  1. 首先,您自己构建HTML代码。在这种情况下,它将是您的标题元素。
  2. 然后解析CSS。
  3. 然后,因为你打电话给document.ready(),Javascript就在里面执行。
  4. 如果您的Javascript完成,那么您最终可以很好地设置所有内容,并且您可以继续实际呈现页面(另一种查看它的方式是“绘制”页面)。
  5. 这是一个在工作中显示此功能的JSFiddle(您需要打开控制台才能看到它有效):http://jsfiddle.net/aLbmB/

    JSFiddle在执行Javascript之前向您显示两个标题元素已解析。如果将for循环中的代码更改为以下内容:

    $("#header2").text($("#header2).text() + "----");
    i--;
    

    您将看到文本永远不会呈现,这有望显示Javascript正在执行,因此,您实际上从未实际访问页面呈现部分。另一个很好的例子是当你通过jQuery从数据库中提取数据并等待所有数据加载时。数据集越大,页面加载所需的时间越长(即使HTML代码已经存在)。

    我在逻辑上考虑这个问题的方式是,在对它们执行任何Javascript之前,首先要很好地设置所有值。然后执行Javascript,一旦完成所有操作,您就可以让用户查看您的成品。当然,当你不使用document.ready()时就不是这种情况,但我想那里的权衡是速度与可预测性(执行中)。

    额外注释(由lazertyuiopl提供):

    "you can trigger a paint of already parsed elements using alert()"提出了一个很好的观点。如果这样做,那么看起来好像每个元素都是从上到下一次绘制一个。我建议检查这个JSFiddle:http://jsfiddle.net/K9kG8/7/

    加载后再次运行它,你会看到我相信Yugal Jindle的预期。

    除此之外:我认为这个问题并不重复,而是通过另一个问题的答案可以澄清的更多问题。换句话说,一个具体的例子。

答案 1 :(得分:0)

以下是发生的事情:(感谢 @Zhouster 获取灵感)

  • 是,部分解析,并创建部分解析树
  • 是的,Javascript(内联或外部)都是解析树阻止
解释 以上代码(问题中) - 发现错误

<html>
<head>
</head>
<body>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <h1>This should show !</h1>               <!-- 1st h1 -->
    <script>
            $(document).ready(function() {    // Mistake: Will be executed later when parse-tree is complete
                // Infinite loop
                for(var i=0; i<100; i++) {
                    i--;
                    console.log($("h1").text());  // Prints both 1st & 2nd h1 in console
                }
            });
    </script>
    <h1>This should *not* show !</h1>        <!-- 2nd h1 -->
</body>
</html>
  • $(document).ready(function() { ... });包含回调函数,当解析树完成时,将执行文档就绪的定义。
  • 因此,循环包含在回调中并等待文档完成解析树
  • 完成解析树后,循环启动,我们可以看到 1st h1 2nd h1 的控制台日志
  • 我们无法在屏幕上看到 h1 ,因为出于某种原因阻止了
  • 由于我们使用文档准备 h1 解析树的一部分,我们可以看到 h1的控制台日志(但 paint被阻止出于某种原因,因此空白屏幕)

稍有不同 - 突出概念:

<html>
<head>
</head>
<body>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <h1>This should show !</h1>               <!-- 1st h1 -->
    <script>
                // **** Without document ready ****
                // Not an infinite loop
                for(var i=0; i<100; i++) {
                    console.log($("h1").text());  // Prints only 1st h1
                }

               // **** Document ready ****
               $(document).ready(function() {
                  // Not an infinite loop
                   for(var i=0; i<100; i++) {
                       console.log($("h1").text());  // Prints both 1st & 2nd h1 in console
                   }
               });
    </script>
    <h1>This should *not* show !</h1>        <!-- 2nd h1 -->
</body>
</html>
  • 因为第一个循环中没有文档就绪所以循环等待解析树< /强>
  • 当我们在部分解析树中有第一个h1 时,循环启动,解析树被阻止,直到脚本完成
  • 这将在控制台上打印仅第一个h1 ,因为它不知道第二个h1
  • 第一个循环完成后,第二个循环再次包含在文档就绪中,因此,它将作为回调存储,脚本将完成并取消阻止解析树
  • 解析树会看到第二个h1 ,解析树将完整
  • 现在,一旦解析树完成,文档就绪将被触发并执行回调
  • 这次(第二次循环),会看到 h1 并将两者的内容打印到控制台
  • 因此, js 阻止解析树的概念保持正确
  • 由于这次循环无限,因此 paint 会被触发,我们可以在屏幕上看到 h1

神秘解决:)

答案 2 :(得分:-1)

你的观念是错误的。

将呈现html并且脚本不会阻止呈现html。但就绪处理程序脚本仅在文档准备就绪后才会调用。

答案 3 :(得分:-1)

这就是Document ready和window.load之间的区别

DOM结构已准备就绪,可以查询。更好的测试是运行jQuery选择器并确认页面上的所有元素都是可访问的。它并不一定意味着要渲染元素。

这是因为,大多数浏览器都会隐藏元素,直到解析CSS为止。