21

Google Closure 库团队成员声称等待 DOMContentReady 事件是一种不好的做法。

简而言之,我们不想等待 DOMContentReady(或更糟糕的加载事件),因为它会导致糟糕的用户体验。在从网络加载所有 DOM 之前,UI 不会响应。所以首选的方法是尽快使用内联脚本。

由于他们仍然没有提供更多细节,所以我想知道他们如何处理 IE 中的Operation Aborted对话框。这个对话框是我知道等待 DOMContentReady(或加载)事件的唯一关键原因。

  1. 你知道还有其他原因吗?
  2. 您认为他们如何处理 IE 问题?
4

7 回答 7

29

先做一点解释:内联 JavaScript 的重点是尽快包含它。但是,“可能”取决于该脚本需要声明的 DOM 节点。例如,如果您有一些需要 JavaScript 的导航菜单,您将在 HTML 中定义菜单后立即包含该脚本。

<ul id="some-nav-menu">
    <li>...</li>
    <li>...</li>
    <li>...</li>
</ul>
<script type="text/javascript">
    // Initialize menu behaviors and events
    magicMenuOfWonder( document.getElementById("some-nav-menu") );
</script>

只要您只处理您知道已声明的 DOM 节点,您就不会遇到 DOM 不可用问题。至于 IE 问题,开发人员必须战略性地包含他们的脚本,以免发生这种情况。这并不是什么大问题,也不是很难解决。真正的问题是“大图”,如下所述。

当然,任何事情都有优点和缺点。

优点

  1. 只要向用户显示 DOM 元素,JavaScript 添加到它的任何功能几乎都可以立即使用(而不是等待整个页面加载)。
  2. 在某些情况下,Pro #1 可以加快感知页面加载时间并改善用户体验。

缺点

  1. 在最坏的情况下,您正在混合演示文稿和业务逻辑,最好的情况是您script在整个演示文稿中混合包含,这两者都可能难以管理。在我看来,以及大部分社区都不能接受。
  2. 正如eyelidlessness所指出的,如果有问题的脚本有外部依赖项(例如库),那么必须首先加载这些依赖项,这将在解析和执行它们时锁定页面渲染。

我使用这种技术吗?不,我更喜欢在页面末尾加载所有脚本,就在结束</body>标记之前。在几乎所有情况下,这对于效果和事件处理程序的感知和实际初始化性能来说都足够快。

其他人可以使用它吗?开发人员将做他们想做/需要做的事情来完成工作,并让他们的客户/老板/营销部门满意。有取舍,只要你理解和管理它们,你应该没问题。

于 2010-01-07T22:35:51.793 回答
1

内联脚本最大的问题是无法正确缓存。如果您将所有脚本存储在一个缩小的 js 文件中(使用编译器),那么浏览器可以为整个站点只缓存一次该文件。

如果您的网站趋于繁忙,从长远来看,这会带来更好的性能。为您的脚本拥有一个单独的文件的另一个优点是您倾向于不“重复自己”并尽可能多地声明可重用的函数。DOMContentReady 不会导致糟糕的用户体验。至少它预先为用户提供了内容,而不是让用户等待 UI 加载,这可能最终成为用户的一大障碍。

此外,使用内联脚本并不能确保 UI 比与 DOMContentReady 一起使用时响应更快。想象一个场景,您使用内联脚本进行 ajax 调用。如果你有一个表格提交罚款。有不止一种形式,你最终会重复你的 ajax 调用..因此每次都重复相同的脚本。最后,它会导致浏览器缓存更多的 javascript 代码,而不是在 DOM 准备好时加载的 js 文件中分离出来。

使用内联脚本的另一大缺点是您需要维护两个独立的代码库:一个用于开发,另一个用于生产。您必须确保两个代码库保持同步。开发版本包含代码的非缩小版本,生产版本包含缩小版本。这是开发周期中的一个大难题。您必须手动将隐藏在那些庞大的 html 文件中的所有代码片段替换为缩小版本,并且最终希望没有代码中断!但是,在开发周期中维护一个单独的文件,您只需要在生产代码库中用已编译的缩小版本替换该文件。

如果您使用 YSlow,您会看到:

使用外部 JavaScript 和 CSS 文件通常会产生更快的页面,因为这些文件由浏览器缓存。每次请求 HTML 文档时,都会下载 HTML 文档中内联的 JavaScript 和 CSS。这减少了 HTTP 请求的数量,但增加了 HTML 文档的大小。另一方面,如果 JavaScript 和 CSS 位于浏览器缓存的外部文件中,则 HTML 文档的大小会减小,而不会增加 HTTP 请求的数量。

当且仅当代码更改如此频繁以至于将其放在单独的 js 文件中无关紧要并且最终会产生与这些内联脚本相同的影响时,我才能保证内联脚本。尽管如此,这些脚本并没有被浏览器缓存。浏览器缓存脚本的唯一方法是将其存储在带有etag的外部 js 文件中。

但是,这绝不是 JQuery vs Google 的闭包。闭包有其自身的优势。然而,闭包库使得将所有脚本都放在外部文件中变得很困难(尽管这不是不可能的,只是让它变得很困难)。您只是倾向于使用内联脚本。

于 2010-07-12T02:51:39.873 回答
0

避免使用内联脚本的一个原因是它要求您在文档中将任何依赖库放在它们之前,这可能会抵消内联脚本的性能提升。我熟悉的最佳实践是将所有脚本(在单个 HTTP 请求中!)放在文档的最后,就在</body>. 这是因为脚本加载会阻塞当前请求和所有子请求,直到脚本完全加载、解析和执行。

没有魔杖,我们总是不得不做出这些取舍。值得庆幸的是,HTML 文档本身将越来越成为占用资源最少的请求(除非您正在做一些愚蠢的事情,比如巨大的data:URL 和巨大的内联 SVG 文档)。对我来说,等待 HTML 文档结束的权衡似乎是最明显的选择。

于 2010-01-07T22:18:00.870 回答
0

我认为这个建议并没有真正的帮助。DOMContentReady 可能只是不好的做法,因为它目前被过度使用(可能是因为 jquery 易于使用的 ready 事件)。许多人将它用作任何javascript 操作的“启动”事件。尽管即使是 jQuery 的 ready() 事件也只是用作 DOM 操作的启动点。

页面加载时的推断性 DOM 操作会导致糟糕的用户体验!!因为它们不是必需的,所以服务器端可以完全生成初始页面。

那么,也许关闭团队成员只是试图转向相反的方向,并阻止人们在页面加载时进行 DOM 操作?

于 2010-01-07T22:27:03.130 回答
0

如果在不考虑图像加载的情况下解析、加载和渲染布局(domready 应该触发的点)花费的时间太长以至于导致明显的 UI 延迟,那么您可能在后端,这是你真正的问题。

此外,页面末尾之前的 JavaScript 会停止 HTML 解析/DOM 评估,直到 JS 被解析和评估。谷歌应该先看看他们的 Java,然后再给出关于 JavaScript 的建议。

于 2011-08-22T20:45:03.213 回答
0

如果您需要自己处理 HTML,Google 的方法似乎很尴尬。他们使用编译的方法,并且可以将他们的大脑周期浪费在其他问题上,考虑到他们应用程序的复杂用户界面,这是正常的。如果您追求要求更宽松的东西(阅读:几乎所有其他东西),也许不值得付出努力。

遗憾的是,GWT 只在谈论 Java。

于 2012-01-05T23:40:10.393 回答
-1

这可能是因为谷歌不在乎你是否没有 Javascript,他们几乎在他们所做的所有事情上都需要它。如果您在已经运行的网站上使用 Javascript 作为附加功能,那么在 DOMContentReady 中加载脚本就可以了。重点是使用 Javascript 来增强用户的体验,而不是在他们没有它的情况下将他们隔离。

于 2010-01-07T22:13:38.383 回答