$.ready()在关闭body标签之前

10
这不是一个真正的编程问题,更像是现实世界中的陈述。
我曾经注意到DOMReady事件非常慢。在浏览jQuery源代码时,我注意到可以使用$.ready()触发jQuery domeready事件。然后我想,将这个简单的执行脚本放在关闭body之前,应该会触发所有先前附加的"onDomReady"监听器。是的,它如预期地工作:
     <script>$.ready()</script>
</body>

这里有两个例子,这个例子测量等待DOMReady时花费的毫秒数:

http://jsbin.com/aqifon/10

如您所见,DOMReady触发器非常慢,用户必须等待整整200-300毫秒,才能启动domready脚本。

无论如何,如果我们在关闭BODY标签之前放置 $.ready(),我们可以得到以下结果:

http://jsbin.com/aqifon/16

看到区别了吗?通过手动触发domready,我们可以减少100-300毫秒的执行延迟。这是一个重要的问题,因为我们可以依赖jQuery在我们看到DOM操作之前处理它们。
现在,有一个问题,我从未见过这被推荐或讨论过,但仍然似乎是一个主要的性能问题。一切都关于优化代码本身,这当然是好的,但如果执行时间延迟太长,用户会看到“未经jQuery处理的内容闪烁”。
有任何想法为什么这不经常被讨论/推荐?

我只能说太棒了。希望没有人提出不这样做的好理由! - Thom Porter
在IE浏览器中,DOM是否在body关闭之前准备就绪? - Ibu
@Ibu 是的,在我所知道的所有浏览器中,当 body 标签关闭时,DOM 已准备就绪。不过,我非常好奇是否存在这种情况的用例... - David Hellsing
1
抱歉问一个愚蠢的问题,但是将某些东西放在文档准备好处理程序中,然后手动触发处理程序与将未包装的JS放在关闭body标记之前有什么区别? - m90
3个回答

4
通过自己触发事件,您告诉ready()处理程序DOM已经加载,但实际上可能没有!没有捷径来达到DOM ready事件。如果确实等待了很长时间,则使用Firebug、Chrome等惊人的调试工具... 检查您的资源及其时间提示。所有信息都以黑白方式显示,并指示是什么导致了长时间等待(请求、渲染、资源数量等)。

你能否提供一个现实世界的情况,当 body 关闭时,DOM 同步准备好? - David Hellsing
谁说只要到达</body>标签,页面就准备好了?DOM不仅仅是<body>。当你使用某种技术来保证DOM已经在所有主流浏览器中完全加载(并且所有竞争条件、浏览器锁等问题都已成功解决)之前,我会在你发布你的技术后立即发布一个真实世界的情况,以确保第一个ready()处理程序被调用。 - ilan berci
好的,从这里开始:http://jsbin.com/aqifon/16。自从jQuery出现以来,我已经编写了许多真实世界的网站,并且我总是在关闭body标签之前放置一个本地触发器,而不是使用DOMReady。我从未听说过任何它无法正常工作的情况。 - David Hellsing

3
实际上,在</body>标签之前放置一个函数调用将使使用jQuery的ready()变得毫无意义。只需放置包含所有其他应在文档就绪时调用的函数调用的本地JS包装器函数调用即可。
一般来说,这是一种工作方法(尽管有些混乱的HTML代码,因此对于完美主义者来说是不可接受的),适用于作者根本不需要/不想使用jQuery的情况。在这种情况下,我更喜欢使用本地的DOMContentLoaded事件处理程序,它被大多数浏览器支持,包括IE9+(对于IE8-,我们可以使用window.load()作为可接受的备选方案)。

我同意你的第一句话,尽管有许多“插件”和其他开发人员附加组件会自动将它们的DOM依赖操作包装在DOMReady处理程序中。我的建议解决方案将比通常发生的更早触发它们。 - David Hellsing

3
有什么想法,为什么这不被更频繁地讨论或推荐?
将JavaScript放置在</body>之前已经被广泛讨论,并且如果您正在寻求更快的页面加载,则建议这样做。手动触发jQuery ready处理程序实际上很少被讨论。为什么?嗯,我认为没有一个单一客观的答案,但我会尝试在此概述一些可能性:
  1. 性能不是jQuery的主要目标(尽管它肯定是一个问题),而性能狂热者通常会寻找更轻的库进行跨浏览器DOM操作和事件处理,或者自己编写。

  2. 这是一个额外的步骤,看起来不够简洁。jQuery试图保持简洁优雅,并推荐额外的步骤来初始化脚本似乎不像是可能发生的事情。他们建议绑定到ready,因此推荐强制使用.ready()并忽略实际的浏览器事件看起来是“错误”的。谁关心这个可能知道在</body>之前初始化脚本是更快的。

  3. 优化DOMContentLoaded听起来像是浏览器供应商的任务。我不确定为什么它更慢,也许没有太多的优化空间 - 在我的理解中,在</body>之前调用init脚本应始终是初始化内容最快的方法(因为它在解析容器<script>标签时立即执行,而浏览器必须完成解析整个文件才能触发DOMContentLoaded)。

您可能还记得不久前,在HTML上到处散布<script>块是常见做法。然后Web标准运动出现了,并推荐了更明智和可维护的方法。其中包括从单个位置启动脚本-最初是window.onload,然后被认为是慢的,然后是DOMContentLoaded及其模拟程序,适用于IE8及以下版本。但是,我们仍然每天在StackOverflow上看到到处都是脚本的意大利面条式HTML。因此,我不确定今天是否建议将脚本放在body结束之前是一个好选择,因为它可能被解释为可以在body内的任何位置添加脚本。
最后,如果您真的关心快速加载脚本,并且您的代码不操作DOM,则将其放在任何样式表之前的<head>中是加载最快的方式。我说这只是为了说明没有银弹,没有一种最优初始化脚本的方法适用于每种情况,而社区坚持推荐看起来合理并倾向于创建更可维护代码的东西,而不是其他性能更好的替代方案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接