【问题标题】:Is $(document).ready() also CSS ready?$(document).ready() 也准备好 CSS 了吗?
【发布时间】:2010-11-22 09:55:05
【问题描述】:

我在 $(document).ready() 上执行了一个脚本,它应该在我的布局中垂直对齐块元素。 90%的时间,它可以正常工作。但是,对于这额外的 10%,会发生以下两种情况之一:

  • 进行居中所需的时间明显滞后,并且块元素跳转到位。这可能只是与性能有关 - 因为页面通常很大,并且有相当数量的 javascript 一次执行。

  • 居中将完全混乱,并且块元素将被推得太远或不够远。似乎它试图计算高度,但测量结果不正确。

为什么在 DOM-ready 上执行脚本不会将所有正确的 CSS 值注入到 DOM 中? (所有 CSS 都在 <head> 通过 <link>)。

另外,这是导致问题的脚本(是的,它直接取自 here):

 (function ($) {
    // VERTICALLY ALIGN FUNCTION
    $.fn.vAlign = function() {
      return this.each(function(i) {
        var ah = $(this).height();
        var ph = $(this).parent().height();
        var mh = (ph - ah) / 2;
        $(this).css('margin-top', mh);
      });
    };
  })(jQuery);

谢谢。

【问题讨论】:

  • 是否涉及图片?即使在计算样式之后,图像加载也会导致重新布局。

标签: javascript jquery css


【解决方案1】:

来自1.3 release notes

ready() 方法不再尝试保证等待所有样式表被加载。相反,所有 CSS 文件都应包含在页面上的脚本之前。 More Information

来自ready(fn) documentation

注意:请确保所有样式表都包含在您的脚本之前(尤其是那些调用 ready 函数的)。这样做将确保在 jQuery 代码开始执行之前正确定义所有元素属性。不这样做会导致零星的问题,尤其是在基于 WebKit 的浏览器(例如 Safari)上。

请注意,上述内容甚至不是关于实际渲染 CSS,因此当ready() 启动时,您可能仍会看到屏幕变化。但它应该可以避免您遇到问题。

其实我觉得有点奇怪,只是把 CSS 放在 JS 上面就可以解决所有问题。 CSS 是异步加载的,因此 JS 加载可以在 CSS 仍在下载的同时开始和结束。那么如果以上是一个解决方案,那么执行任何 JS 代码都会暂停,直到所有之前的请求都完成?

我做了一些测试,确实,有时 JS 会延迟到 CSS 加载完成。我不知道为什么,因为瀑布显示JS在下载CSS完成之前很久就完成了加载。

some HTMLits results 参见 JS Bin(这有 10 秒延迟),its waterfall results 参见webpagetest.org。这使用了来自 Steve Souders 的 cuzillion.com 的一些脚本来模拟缓慢的响应。在瀑布中,对 resource.cgi 的引用是 CSS。因此,在 Internet Explorer 中,第一个外部 JS 在请求 CSS 后立即开始加载(但该 CSS 将需要另外 10 秒才能完成)。但是第二个<script> 标记在 CSS 完成加载之前不会执行:

<link rel="stylesheet" type="text/css" href=".../a script that delays.cgi" />

<script type="text/javascript" src=".../jquery.min.js"></script> 

<script type="text/javascript"> 
  alert("start after the CSS has fully loaded"); 
  $(document).ready(function() { 
    $("p").addClass("sleepcgi"); 
    alert("ready"); 
  });         
</script> 

Another test 在获取 jQuery 后使用第二个外部 JS,shows 表示直到 CSS 加载后才开始下载第二个 JS。这里,resource.cgi 的第一个引用是 CSS,第二个是 JS:

移动样式表下面所有 JS 确实表明 JS(包括 ready 函数)运行得更早,但即便如此 jQuery 应用的类——当 JS runs-- 在我的 Safari 和 Firefox 快速测试中正确使用。但是像$(this).height() 这样的东西在那个时候会产生错误的值是有道理的。

但是,additional testing 表明 在加载之前定义的 CSS 之前停止 JS 不是一般规则。使用外部 JS 和 CSS 似乎有一些组合。我不知道这是怎么回事。

最后一点:由于JS Bin在从裸URL运行时在每个脚本中都包含Google Analytics(如jsbin.com/aqeno测试结果实际上是由JS Bin改变的...看起来编辑 URL 上的输出选项卡(例如 jsbin.com/aqeno/edit)不包含额外的 Google Analytics(分析)内容,并且肯定会产生不同的结果,但该 URL 很难使用webpagetest.org 进行测试。strager 给出的对Stylesheets Block Downloads in Firefox and JavaScript Execution in IE 的引用是一个更好的理解的良好开端,但我还有很多问题......另请注意 Steve Souders 的IE8 Parallel Script Loading,这会使事情变得更加复杂。(上面的瀑布是使用 IE7 创建的。)

也许人们应该简单地相信发行说明和文档...

【讨论】:

  • Cuzillion (stevesouders.com/cuzillion) 应该可以帮助您了解不同类型的对象是如何在不同的浏览器中加载的。
  • ...但它仍然不是最终答案。也许事情是否在&lt;head&gt;&lt;body&gt; 中甚至很重要?考虑到 Firefox 中的样式表阻止下载和 IE 中的 JavaScript 执行(那么,其他浏览器呢?)和 IE8 并行脚本加载我想这个垂直可能会出现很多问题对齐脚本。顺便说一句:webpagetest.org/result/090825_24AP IE8 中后者的瀑布不显示并行加载,看起来像 IE7 webpagetest.org/result/090825_24AQ
  • @Bryan,我认为你的问题,尤其是 IE8 并行脚本加载,会让我在接下来的几周里睡得更糟...... ;-) 至于你的问题:请参阅以下 JS Bin 以获取具有 vAlign 功能的版本(稍作更改以允许使用提供的 CSS),这确实表明 $(this).height(); 在加载 CSS JavaScript 之后可能会产生零,但在加载 之前 时似乎很好。但是,仍然不知道 为什么,恐怕每个浏览器的行为可能不同:jsbin.com/ofola/edit
  • 浏览器异步下载样式表,但在样式表加载之前会阻止 其下的脚本执行。他们猜测作者会想要在后续脚本中查询样式信息,因此他们必须阻止执行以保证样式可用。
  • @sam 它实际上会阻塞直到元素被渲染,因此 js 可以查询值,而不仅仅是在样式表加载之前。这称为布局垃圾,它是性能问题的常见来源。
【解决方案2】:

根据 HTML5,DOMContentLoaded 是一个普通的 DOM 就绪事件,不考虑样式表。 然而,HTML5 解析算法要求浏览器推迟脚本的执行,直到所有以前的样式表都加载完毕。 (DOMContentLoaded and stylesheets)

molily's tests (2010)

  • IE 和 Firefox 阻止所有后续脚本执行,直到加载样式表
  • Webkit 仅阻止外部脚本的后续执行 (&lt;script src&gt;)
  • Opera 没有阻止任何脚本的后续执行

All modern browsers now support DOMContentLoaded (2017) 所以他们现在可能已经标准化了这种行为。

【讨论】:

    【解决方案3】:

    CSS/JavaScript/JQuery 排序对我不起作用,但以下方法可以:

    $(window).load(function() { $('#abc')...} );
    

    【讨论】:

    • 这里也一样。我在 IE9 中遇到了在样式渲染之前运行 js 的问题,但是用它替换 $(document).ready 解决了我的问题。奇怪的。无论如何谢谢:)
    • 甚至 jquery 都这样写:“虽然 JavaScript 提供了在页面呈现时执行代码的加载事件,但在完全接收到所有资产(例如图像)之前,不会触发此事件。” api.jquery.com/ready 所以我也会尝试用这个来解决
    • 我测试过,css/js 重新排序在加载外部样式表时并没有为我解决这个问题,这在 Opera 和 Chrome 中都是如此。
    • 这是核选项。加载事件通常在 dom-ready 之后 方式 发生 - 只需考虑大量图像资产、Facebook iframe 等的影响。如果脚本延迟到加载事件之后,可能需要几秒钟才能完成执行。
    【解决方案4】:

    据我所知,在加载 DOM 时会触发 ready 事件 - 这意味着所有阻塞请求(即 JS)都已加载并且 DOM 树已完全绘制成图形。 IE 中的就绪状态依赖于比大多数其他浏览器更慢的事件触发(document.readyState 更改与 DOMContentLoaded),因此时间也取决于浏览器。

    非阻塞请求(如CSS和图片)的存在是完全异步的,与就绪状态无关。如果您处于需要此类资源的位置,则需要依赖于良好的旧 onload 事件。

    【讨论】:

    • 今天在进行一些测试时,我了解到以某种方式下载 CSS 可能会被阻塞(用于执行一些下一个 &lt;script&gt; 标签,而不是用于触发 ready 函数本身)。但如果那是投反对票的原因,那么我也很乐意看到一些解释。本来可以让我免于进行一些测试...
    • 我不是反对你的人,但你可能想看看这个:stevesouders.com/cuzillion/…
    • CSS 下载是非阻塞的,但 they can block execution of subsequent scripts.
    • 上面的链接必须是 MOST 令人困惑的说法,即 iframe 脚本可能会被父级中的样式表阻止。我是不是误会了?说真的!
    【解决方案5】:

    当所有 DOM 节点都可用时触发 DOM 就绪。它与 CSS 无关。尝试定位之前的样式或尝试以不同的方式加载它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-05
      • 1970-01-01
      • 2023-03-30
      • 1970-01-01
      • 1970-01-01
      • 2014-04-20
      • 2014-09-05
      • 2011-07-14
      相关资源
      最近更新 更多