$(document).ready() 函数何时触发?

7

这个问题的评论让我想到了一些事情。 $(document).ready() 函数什么时候会触发?显而易见的答案是“当文档准备就绪时”,但具体是什么时候呢?

例如,如果我打开输出缓冲并在 PHP 继续执行的同时刷新输出, 那么输出是否会发送到浏览器?那么在 PHP 脚本完成执行之前,文档是否已经准备就绪,或者该事件是否等待请求完成?


编辑:

回复基本上认为事件在客户端准备就绪时触发。

为了更好地理解(我应该首先做的),我刚刚设置了一个测试:

<?php ob_start(); ?>
<html>
<head>
    <script type="text/javascript" src="lib/js/jquery-1.7.1.min.js"></script>
    <script type="text/javascript">
        $(document).ready(function() {
            alert("READY");
        });
    </script>
</head>
<body>
<?php
    ob_flush();
    for ($i=0; $i<999999; $i++) {
        echo "HELLO$i\n";
        ob_flush();
    }
?>
</body>
</html>

在这个例子中,结果是内容立即显示在页面上,但警告直到循环完成或脚本超时(30秒)才会发生。
到了依赖于使用哪个浏览器的程度,我尝试在我的循环中插入这个。
if ($i == 99) {
    echo "</body></html>";
}

Chrome似乎通过在页面末尾放置这些标签来自动纠正它(如Web开发者检查器中所见)。查看页面源代码时,它显示在中间,那里我使用了echo。


1
ready()总是在php打印html页面完成后。换句话说,它总是在"</body>"发送之后。 - dandavis
8
“ready”事件是浏览器端的概念。当浏览器处理了<html>内容并准备好DOM时,它会认为页面已经“准备就绪”,但某些CSS和图像仍可能未完成加载。浏览器并不知道或关心服务器在做什么,至少不会直接关心。 - Pointy
根据文档,它在“DOM层次结构完全构建”之后立即触发,但在页面上实际加载任何内容之前。因此,如果您有图像,它可能会在它们加载之前触发(这就是为什么jQuery也提供了“load”的原因)。 - scrappedcola
没有明确的答案。正如@Pointy所说,这取决于浏览器认为何时完成/准备好。一些格式不正确的HTML可能不包括适当的</body></html>标记,但浏览器仍将以怪异模式呈现并发出DOMReady事件。同时,您可以关闭输出缓冲区或刷新缓冲区,并从服务器流式传输输出,因此由浏览器确定何时认为您已完成流式传输。 - vol7ron
ready() 不需要 </body>,只是通常在 PHP 完成并在 ready() 触发之前到达 /body。 - dandavis
5个回答

6
jQuery的文档中的ready事件会在jQuery确定DOM可用时立即触发。确切的机制取决于浏览器。
请查看相关源代码
首先,检查是否已经可以访问DOM以绑定事件监听器。如果是,则回调将立即被安排执行 - 尽管它们实际上不会立即被执行,以允许当前执行槽中已经占用的代码取消处理程序(如果需要)。
如果DOM尚不可访问,则尝试将事件监听器绑定到浏览器的本地DOMContentLoaded事件 - 这是请求浏览器在DOM可用时通知您的“正确”本地方式,但这是一个相对较新的特性。如果不可能(这几乎肯定表示您的代码正在旧版本的IE中运行),则代码会退回到一些机制:
  • 尝试将事件onreadystatechange附加到文档上。这并不是绝对可靠的,而且会比DOMContentLoaded晚一些,但它相当不错。
  • 回退到window对象的load事件。这通常比DOM可用时间晚得多,但它是一个最后的备份,以确保事件最终总是会触发。
  • 最坏的情况:不断轮询DOM直到它变得可用。

从PHP的角度来看,这是可能的(但不太可能)在你的PHP脚本执行完之前发生。有些情况下(例如长轮询),事件将在你的脚本完成之前触发,但这仅会发生在旧版浏览器中。然而,在这些情况下,你根本不应该使用这些事件,你只需要将适当的<script>元素放置在页面的主体中,以便它们在加载时立即执行,无需等待DOM的其余部分。

就我个人而言,我从来不使用任何这些基于加载的事件,更或者是出于这个原因。你的想法可能会不同。


3
例如,如果我打开输出缓冲并在PHP继续执行时刷新了输出,那么这不会发送输出到浏览器吗?
是的,它会发送输出,但这并不意味着浏览器认为服务器已经完成。我知道这不是PHP,但我喜欢Perl文章Suffering from Buffering。当UserAgent认为准备好时,文档就已经准备好了。但是,浏览器将保持套接字打开,同时它仍然认为正在接收数据,而且没有发送END信号。
那么,在PHP脚本完成执行之前文档是否有任何方式可以准备好,或者事件是否等待请求完成?
通常,浏览器将等待服务器完成发送数据。如果您正在刷新输出,那么可能在脚本仍在运行时Web服务器会超时,例如,我认为Apache默认为2分钟。如果服务器发送结束信号,则您的文档已完成,您的浏览器可能会准备DOM并触发DOMReady事件,即使您的脚本仍在服务器上运行。
与其他评论相反,</body></html>并不是DOM准备就绪的良好指标,主要是因为页面可能存在格式错误(拼写错误或不包含这些结束标记)。在这些情况下,浏览器仍会以怪异模式呈现并触发DOMReady。

0

0

它在DOM层次结构完全构建并且没有更多的PHP代码需要执行时触发(因为PHP代码在页面发送之前执行)。

这意味着它会在客户端接收到页面后立即执行。其他东西可能会在此之后加载,例如图像、CSS和其他Javascript。


0

Document.ready()会在DOM加载完成时触发。当所有HTML都存在时,DOM ready事件将被触发。

PHP不会干扰DOM ready,因为PHP是一种服务器端编程语言。它将从服务器处理,服务器发送请求的页面,然后您的浏览器加载页面并触发DOM ready事件。

DOM ready和window load之间的区别在于,load将等待每个图像/ CSS加载完成。标签存在于HTML中,但图像未显示。

基本上,我们可以说当浏览器读取HTML结束标记(</html>)时,DOM ready就会被触发。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接