【问题标题】:$(document).ready() fires too early$(document).ready() 过早触发
【发布时间】:2012-02-03 20:15:36
【问题描述】:

所以,我需要用 javascript 知道元素的宽度,我遇到的问题是函数触发得太早,并且当完全应用 css 时宽度会发生变化。据我了解,文档完成时会触发 $(document).ready() 函数,但它似乎没有那样工作。

无论如何,我确信通过代码我的问题将被理解(这是一个简化的示例):

<html>
<head>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
    <link href='http://fonts.googleapis.com/css?family=Parisienne' rel='stylesheet' type='text/css'>

    <style type="text/css">
        #target {
            font-family: 'Parisienne', cursive;
            float: left;
        }
    </style>
</head>
<body>
    <div id="target">Element</div>
</body>
</html>

<script type="text/javascript">
    $(document).ready(function(){
        console.debug($('#target').outerWidth());
        alert('hold on');
        console.debug($('#target').outerWidth());
    });
</script>

我想知道#target div 的宽度,问题是在警报之前执行的代码给出的输出与之后的不同,大概是因为字体没有完全加载并且它正在测量 div默认字体。

它在 Google Chrome 中可以正常工作,但在 IE 和 Firefox 上却不行。

【问题讨论】:

  • 我可以在 2013 年 11 月 24 日确认,当您点击浏览器的刷新按钮时,这个问题在 JQuery 2.x 上仍然存在。转到此fiddle。当您第一次加载小提琴时,大多数时候一切都应该正常工作。如果您将鼠标光标放在 URL 中并按 Enter 键,它也可以工作。但是,如果您单击刷新按钮或按 CTRL+R,事情将一败涂地。
  • 我试图实现一个“倒计时锁存器”来测量宽度和高度,只有当窗口加载触发并且依赖字体完成触发时。看看是否有帮助:http://jsfiddle.net/jLDbX/1/。在这个小提琴中,一切似乎都运行得恰到好处。但在我的现实世界应用程序中,我不断收到错误。不过对你来说,它可能有用。

标签: javascript jquery dom


【解决方案1】:

如果依赖已经加载的外部内容(例如图片、字体),则需要使用 window.load 事件

$(window).on("load", function() {
    // code here
});

this article 中描述了这些事件的行为:

有 [a] 就绪状态,但称为 DOM 就绪。这是浏览器实际构建页面但仍可能需要抓取一些图像或 Flash 文件的时候。

编辑:changed syntax to also work with jQuery 3.0,正如 Alex H 所指出的那样

【讨论】:

  • 两年后,仍然有帮助!
  • 在 JQuery 3.0 中,您应该使用语法 $(window).on('load', function() { });,因为不推荐使用 $(window).load()。
  • @AlexH,说得好。 $(window).load() 在 jQuery 1.8 中已弃用。此外,它令人困惑,因为 jQuery 中有两个 .load() 方法(在删除事件处理之前)。
  • 由于这是最佳答案,值得一提的是,实际上在 jQuery 3.0 中 on 方法已被贬低,应该使用 .ready()/.load() api.jquery.com/ready/#ready-handler
  • @darth0s 不, $(window).on('load',...) 语法没有改变,实际上 $(window).load() 已被删除。但是,您对 .ready() 案例是正确的。
【解决方案2】:

引用 OP:

“据我所知,$(document).ready() 函数是在文档完成时触发的,”

$(document).ready() 在 DOM(“文档对象模型”)完全加载并准备好进行操作时触发。 DOM 与“文档”不同。

W3C - DOM Frequently Asked Questions

你可以试试$(window).load()函数...

$(window).load(function() {
    // your code
});

它会等待页面的所有资源(如图像和字体等)在触发前完全加载。

【讨论】:

    【解决方案3】:

    一旦 DOM 完成,jQuery .ready() 函数就会触发。这并不意味着此时所有资源(如图像、CSS 等)都已加载,因此元素的大小可能会发生变化。

    如果您需要元素的大小,请使用 $(window).load()。

    【讨论】:

      【解决方案4】:

      “就绪”事件在 DOM 加载时触发,这意味着何时可以安全地使用标记。

      要等待加载所有资源(css、图像、外部 javascript...),您宁愿使用 load 事件。

      $(window).load(function() {
          ...
      });
      

      【讨论】:

        【解决方案5】:

        您可以使用$(window).load(),但这将等待所有资源(例如,图像等)。如果你只想等待字体被加载,你可以尝试这样的事情:

        <script type="text/javascript"> 
            var isFontLoaded = false;
            var isDocumentReady = false;
            $("link[href*=fonts.googleapis.com]").load(function () {
                isFontLoaded = true;
                if (isDocumentReady) {
                    init();
                }
            });
            $(document).ready(function () {
                isDocumentReady = true;
                if (isFontLoaded) {
                    init();
                }
            });
            function init () {
                // do something with $('#target').outerWidth()
            }
        </script> 
        

        免责声明:我不完全确定这会奏效。 &lt;link&gt; onload 事件可能会在样式表被解析后立即触发,但在其外部资源下载之前。也许您可以添加一个隐藏的&lt;img src="fontFile.eot" /&gt; 并将您的 onload 处理程序放在图像上。

        【讨论】:

          【解决方案6】:

          我在 IE9 和 IE10 中绝对重复地看到过同样的问题。 jquery ready() 调用触发并且我的

          之一不存在。如果我检测到这一点,然后在短暂的 timeout() 后再次调用它就可以正常工作。

          为了安全起见,我的解决方案有两个:

          1. 在文档末尾附加 然后在 ready() 回调中检查该变量,并且

          2. 检查 $('#lastElementInTheDocument').length > 0

          是的,我知道这些都是令人讨厌的黑客行为。但是,当 ready() 没有按预期工作时,需要某种变通方法!

          顺便说一句,“正确”的解决方案可能包括在标题中设置 $.holdReady,并在文档末尾清除它。但当然,真正正确的解决方案是让 ready() 起作用。

          【讨论】:

          • 我想我也看到了这种行为。也许解决方案是将 document.ready 命令放在页面底部,这似乎是这些天更常见的做法。我看到了这个问题,但我目前在 标记中有我的 document.ready 命令。
          【解决方案7】:

          $(document).ready() 过早触发 问题有时会发生,因为您错误地声明了 jQuery onReady 函数。

          如果遇到问题,请确保您的函数声明完全像这样:

           $(document).ready(function() 
           {
             // put your code here for what you want to do when the page loads.
           });
          

          例如,如果您忘记了匿名函数部分,代码仍然会运行,但会“乱序”运行。

          console.log('1');
          $(document).ready()
          {
            console.log('3');
          }
          console.log('2');
          

          这将输出

          1
          3
          2
          

          【讨论】:

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