究竟何时执行$(document).ready回调?


74

假设我们将.click()处理程序附加到回调中的anchor(<a>)标签上$(document).ready。该处理程序将取消默认操作(在之后href)并显示警报。

我想知道的是,回调将在何时准确执行,用户是否可以单击锚点(该文档已在浏览器中显示),但该事件尚未附加。

这是包含锚点的不同HTML页面,但是脚本的包含顺序不同。它们之间有什么区别(如果有)?不同的浏览器会表现不同吗?

第1页:

<html>
<head>
    <title>Test 1</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
    <script type="text/javascript">
    $(function() {
        $('a').click(function() {
            alert('overriding the default action');
            return false;
        });
    });
    </script>
</head>
<body>
    <a href="http://www.google.com">Test</a>
</body>
</html>

第2页:

<html>
<head>
    <title>Test 1</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
</head>
<body>
    <a href="http://www.google.com">Test</a>
    <script type="text/javascript">
    $(function() {
        $('a').click(function() {
            alert('overriding the default action');
            return false;
        });
    });
    </script>
</body>
</html>

Page3:

<html>
<head>
    <title>Test 1</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
    <a href="http://www.google.com">Test</a>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
    <script type="text/javascript">
    $(function() {
        $('a').click(function() {
            alert('overriding the default action');
            return false;
        });
    });
    </script>
</body>
</html>

因此,是否有可能href通过单击锚点将用户重定向到,而从没有看到警报(当然,忽略javascript禁用的情况)?我提供的任何示例都可能发生这种情况吗?

我需要做的就是确保click事件处理程序已附加到锚点上,然后用户才有可能单击该锚点。我知道我可以提供一个空的href,然后在javascript中逐步增强它,但这是一个更普遍的问题。

如果HTML是由Web服务器快速生成但jquery库需要花费时间从远程服务器获取的,将会发生什么情况?这会影响我的情况吗?与加载DOM相比,包含脚本的顺序是什么?它们可以并行完成吗?

Answers:


59

示例3将最有可能使用户单击链接,而处理程序尚未附加该链接。由于您是呈现链接加载jQuery库的因此,如果Google的服务器运行缓慢(或DNS查找需要一秒钟左右),或者用户计算机处理jQuery的速度很慢,则链接将没有其单击处理程序用户尝试单击时将其附加。

发生这种情况的另一种情况是,如果您的加载页面很大或很慢,并且此链接位于顶部。然后,当DOM的一部分可见时,它可能尚未完全准备就绪。如果您遇到这样的问题,最安全的做法是:

  1. head示例1或2中加载jQuery
  2. 将click事件附加在<a>元素之后,但不要附加在DOMReady回调中。这样,它将立即被调用,而不会等待文档的其余部分。

呈现元素后,可以从DOM中获取它,随后jQuery可以访问它:

<a href="http://www.google.com">Test</a>
<script type="text/javascript>
    // No (document).ready is needed. The element is availible
    $('a').click(function() {
        alert('overriding the default action');
        return false;
    });
</script>

此外,以user384915的注释为基础,如果该操作完全依赖于JavaScript,则甚至不将其呈现为HTML的一部分,请在jQuery准备就绪后将其添加:

<script type="text/javascript">
jQuery(function($){
   $("<a />", { 
      style: "cursor: pointer", 
      click: function() {
        alert('overriding the default action');
        return false;
      },
      text: "Test"
   }).prependTo("body");
});
</script>

15

您在这里有几个不同的问题

究竟何时执行$(document).ready回调?

DOM完全加载后立即执行。并非所有内容(例如图像)都像.load()一样完成下载。(通常)在此之前,基本上是在页面自身建立时。

我想知道的是何时确切执行回调

单击时。

用户是否可以单击锚点(文档已显示在浏览器中)但尚未附加事件。

对的,这是可能的。但是将其放在.ready()中会给您带来最大的机会,那就是不会。只有两种方法可以做到“更加确定”不会。这些实际上是在链接本身上使用“ onclick”,并将javascript直接放在链接之后(而不是放在.ready()中),以便在创建链接后立即执行。

同样,您提供的2个代码示例的工作方式也没有区别。但是,在第二个代码中,您无需将代码放在.ready()中,因为它存在于链接之后,所以将始终在创建链接之后执行该代码。如果从.ready()中删除它,那将是我上面介绍的两种方法中的第一种。

另外,不要将“ return false”置为;在回调中,最好使用.preventDefault()和.stopPropagation(),这将使您指定是要阻止默认操作还是要阻止事件冒泡,或同时使用两者。


因此,您要说的是,实现我正在寻找的内容的唯一方法(确保用户在重定向之前会看到警报)是在链接之后使用onclick或附加click处理程序(不使用$(document).ready)?
Darin Dimitrov

根据他是否启用了输出缓冲或使用分块编码,示例会有所不同。
gblazex

就我的目标而言,假设启用了缓冲,这三个示例中哪一个最好?那么分块编码呢?
Darin Dimitrov

2
使用onclick是确定的唯一方法。当使用.ready()时,它极不可能发生,并且如果不发生实际上是一件坏事,那么最好是找到另一种方式来做您正在做的事情。请记住,并不是每个人都打开了javascript,因此很有可能有人点击该链接并执行默认操作。
马特·埃文诺夫

2

这取决于很多事情。例如,如果您使用了分块编码,则用户可能会获得分块,但由于文档尚未准备好,因此不会附加侦听器。

jQuery ready事件是W3C兼容浏览器中的DOMContentLoaded事件(在HTML5规范中进行了标准化),在其他浏览器中(例如IE中的readystate ),它是其中的一些替代方法

DOMContentLoaded(MDC)

解析文档后,在页面的Document对象上触发。在事件触发时,页面的DOM已准备就绪。

因为这是在呈现之前发生的,所以可以肯定地说,在此事件之后执行的回调将能够防止用户在尚未准备就绪的页面上进行交互。

但是正如Peter Michaux在他的文章中指出的那样,由于浏览器实现此事件的方式存在差异,“在四大浏览器中,不可能有一种强大的方法来提早实现生命。”

因此,我想说您不能100%依赖jQuery ready事件,但是大多数情况下它都可以正常工作



1

您的第三个示例提供了在没有附加覆盖处理程序的情况下用户单击的最大机会。浏览器通常先下载并解析每个浏览器,<script>然后再继续浏览下一个。您是从外部来源(Google)引入jQuery的,尽管它可能可靠,但可能不可用或加载缓慢。<script>在文档末尾都有两个块<body>,因此在处理最后两个脚本时,页面的先前区域可能已经下载并呈现到屏幕上。虽然提倡此方法向用户提供响应性的页面加载体验,但他们可能会在此不确定的时期内单击,并且当然还没有附加覆盖处理程序。

关于脚本和加载顺序,有一篇有趣的YUIblog文章 在这里


0

确保可以“欺骗”警报警告(即使启用了Javascript)。尝试在url字段中拖动链接,您将看到它会在没有该警告的情况下执行。如果链接正在触发删除操作,则这尤其成问题。

关于document.ready回调-我也有这样的问题。让我解释。我们正在做一个项目,其中所有表单都显示在弹出窗口(jQuery窗口)中。因此,当弹出窗口关闭(暂时)时,页面会重新加载,并且我遇到了一些情况,当我重定向到另一个屏幕而不是打开新的弹出窗口时。

完全同意user384915有关将javascript直接放在onClick事件上,甚至更好的href标签。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.