【问题标题】:When exactly the $(document).ready callback is executed?何时执行 $(document).ready 回调?
【发布时间】:2010-07-11 02:40:40
【问题描述】:

假设我们在$(document).ready 回调中将.click() 处理程序附加到锚点(<a>) 标记。此处理程序将取消默认操作(遵循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>

第3页:

<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 相比,包含脚本的顺序是什么?它们可以并行完成吗?

【问题讨论】:

    标签: javascript jquery


    【解决方案1】:

    示例 3 最有可能用户能够在处理程序尚未附加自身的情况下点击链接。由于您是在 渲染链接之后加载 jQuery 库,如果 Google 的服务器有点慢(或者 DNS 查找需要一秒钟左右),或者用户计算机处理 jQuery 的速度很慢,那么当用户尝试单击链接时,链接不会附加其单击处理程序。

    另一种可能发生这种情况的情况是,如果您有一个非常大或加载缓慢的页面,并且此链接位于顶部。那么当部分可见时,DOM 可能还没有完全准备好。如果您遇到这样的问题,最安全的做法是:

    1. head 中加载 jQuery(示例 1 或 2)
    2. &lt;a&gt; 元素之后立即附加点击事件,但不在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>
    

    【讨论】:

      【解决方案2】:

      这里有几个不同的问题

      什么时候 $(document).ready 回调被执行了吗?

      它会在 DOM 完全加载后立即执行。不是当一切(例如图像)都像 .load() 那样完成下载时。 (通常)在此之前,基本上是在页面自身构建时。

      我想知道的是什么时候 正是回调将执行

      当它被点击时。

      用户是否可以点击 在锚点上(文件已 显示在浏览器中)但事件 还没有附上。

      是的,这是可能的。但是把它放在 .ready() 中会给你最好的机会,它不会。只有两种方法可以“更确定”它不会。这些实际上是在其自身的链接上使用“onclick”,并将 javascript 直接放在链接之后(而不是在 .ready() 中),以便在创建链接后立即执行。

      此外,您提供的 2 个代码示例的工作方式没有区别。但是,在第二个中,您不需要将代码放在 .ready() 中,因为它存在于链接之后,它总是会在链接创建后执行。如果您将其从 .ready() 中删除,它将是我上面描述的两种方式中的第一种。

      另外,而不是把'return false;'在您的回调中,最好使用 .preventDefault() 和 .stopPropagation() 这将让您指定是否要阻止默认操作或阻止事件冒泡,或两者兼而有之。

      【讨论】:

      • 所以你说实现我正在寻找的唯一方法(保证用户在重定向之前看到警报)是使用 onclick 或附加 click 处理程序就在链接之后(不使用$(document).ready)?
      • 示例不同,具体取决于他是否启用了输出缓冲或使用分块编码。
      • 在启用缓冲的情况下,就我的目标而言,这三个示例中哪一个是最好的?分块编码呢?
      • 使用 onclick 是唯一确定的方法。使用 .ready() 时,它不太可能不会发生,如果它没有发生实际上是一件坏事,最好找到另一种方法来做你正在做的任何事情。请记住,并不是每个人都打开了 javascript,因此很可能有人单击该链接并执行默认操作。
      【解决方案3】:

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

      jQuery 就绪事件是 W3C 兼容浏览器中的 DOMContentLoaded 事件(在 HTML5 规范中标准化),以及其他一些替代方法(如 IE 中的 readystate) .

      DOMContentLoaded (MDC)

      在页面的 Document 对象上触发 当文件的解析是 完成的。到这个活动的时候 触发,页面的 DOM 已准备就绪。

      因为这是在渲染之前发生的,所以在此事件之后执行的回调将能够阻止用户在未准备好的页面上进行交互是一个可靠的假设。

      但正如 Peter Michaux 在 his article 中指出的那样,由于浏览器实现此事件的方式存在差异“在四大浏览器中无法实现一种强大的早期激活技术。” p>

      所以我会说你不能 100% 依赖 jQuery 就绪事件,但 大多数时候它会工作 很好。

      【讨论】:

        【解决方案4】:

        在 YUI 中,有 onContentReady()onAvailable() 方法。不幸的是,在 jQuery 中没有等价的东西。但是有一个插件受到了他们的启发:

        http://www.thunderguy.com/semicolon/2007/08/14/elementready-jquery-plugin/

        这应该允许您在 DOM 完全加载之前将事件绑定到锚点。

        【讨论】:

          【解决方案5】:

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

          有一篇关于脚本和加载顺序的有趣 YUIblog 文章here

          【讨论】:

            【解决方案6】:

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

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

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-04-20
              • 2014-06-18
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多