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

时间:2010-07-10 17:47:54

标签: javascript jquery

假设我们将.click()处理程序附加到$(document).ready回调中的锚点(<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中逐步增强它,但这是一个更普遍的问题。

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

6 个答案:

答案 0 :(得分:60)

示例3 将有最高的机会用户能够在没有处理程序附加的情况下点击链接。由于您在之后加载了jQuery库,所以如果Google的服务器有点慢(或者DNS查找需要一秒左右),或者用户计算机处理jQuery的速度很慢,当用户尝试单击它时,链接将不会附加其单击处理程序。

另一种可能发生这种情况的情况是,如果您有一个非常大或很慢的加载页面,并且此链接位于顶部。然后,当DOM的一部分可见时,DOM可能还没有完全就绪。如果您遇到这样的问题,最安全的事情要做的是:

  1. head(示例1或2)
  2. 中加载jQuery
  3. <a>元素之后立即附加click事件,但不在DOMReady回调中附加。这样它将立即被调用,不会等待文档的其余部分。
  4. 一旦元素被渲染,它就可以从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>
    

答案 1 :(得分:15)

这里有几个不同的问题

  

完全是$(文件).ready   回调被执行了吗?

只要DOM完全加载就会执行。不是当所有的东西(比如图像)都完成下载时,就像.load()一样。它(通常)在此之前,基本上就是它自己构建的页面。

  

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

单击时。

  

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

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

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

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

答案 2 :(得分:2)

这取决于很多事情。例如,如果你有分块编码,那么用户可能会获得一个块,但是因为文档还没有准备好,所以不会附加监听器。

jQuery ready事件是符合W3C标准的浏览器中的 DOMContentLoaded 事件(在HTML5规范中标准化),以及其他一些替代(如IE中的readystate)

  

DOMContentLoaded(MDC)

     

在页面的Document对象中被触发   解析文档时   完了。到这个事件的时候   火灾,页面的DOM准备就绪。

因为在渲染之前会发生这种情况,所以在此事件之后执行的回调将能够阻止用户在非就绪页面上进行交互,这是一个可靠的假设。

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

所以我会说你不能100%依赖jQuery ready事件,但大部分时间它都能正常工作就好了。

答案 3 :(得分:2)

在YUI中,有方法onContentReady()onAvailable()。不幸的是,jQuery中没有相同的东西。然而,有一个受它们启发的插件:

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

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

答案 4 :(得分:1)

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

关于脚本和加载顺序here,有一篇有趣的YUI博客文章。

答案 5 :(得分:0)

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

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

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