18

以下两种解决方案有什么区别?特别是,是否有充分的理由支持 2 而不是 1。(注意:请假设要加载的脚本的名称是已知的。问题是创建一个最小脚本来加载给定脚本中的脚本是否有价值情况 )

1 - 底部的脚本

<html>
<body>
...
...
<script src='myScript.js'></script>
</body>
</html>

2 - 底部的脚本加载外部脚本

<html>
<body>
...
...
<script>
    // minimal script to load another script
    var script = document.createElement('script');
    script.src = 'myScript.js'
    document.body.appendChild(script);
</script>
</body>
</html>
4

5 回答 5

11

第二个的一个重要特性是它允许浏览器立即完成页面解析,而无需等待脚本加载。这是因为第一个示例允许脚本用于document.write更改<script>标记周围的解析状态,而第二个示例则不允许。

现在,我们知道它位于页面底部,因此没有任何重要的内容需要解析,但这仍然是一个重要的区别。直到解析完成,浏览器才会触发流行DOMContentLoaded事件。在方法 1 中,事件在脚本加载并执行后触发。在方法 2 中,事件在脚本开始加载之前触发。

这里有些例子。在这些演示中,DOMContentLoaded侦听器将背景颜色更改为黄色。我们尝试加载一个需要 3 秒才能加载的脚本。

  1. http://jsfiddle.net/35ccs/
  2. http://jsfiddle.net/VtwUV/

(编辑:也许 jsfiddle 不是托管这些演示的最佳场所。在加载缓慢的脚本之前它不会显示结果。请确保在加载后再次单击“运行”,看看会发生什么。)

选择最适合您的应用的方法。如果您知道之前需要运行脚本DOMContentLoaded,请使用方法 1。否则,方法 2 在大多数情况下都很好。

于 2014-04-02T22:25:01.280 回答
5

1.底部的脚本

当您使用“同步”脚本标记时,它将阻止浏览器呈现页面,直到脚本被加载并执行。这种方法有以下效果:

  • 无论您将脚本标记放在何处,浏览器都无法触发DOMContentLoaded,直到脚本被下载并执行。

  • 将这样的脚本标签放在底部只能确保浏览器在被脚本阻止之前已经呈现了所有内容。

2.底部脚本加载外部脚本

当您使用 JavaScript 注入脚本标签时,它将创建一个不会阻止浏览器的“异步”脚本标签。这种方法有以下效果:

  • 无论您将生成脚本标记的 JavaScript 代码放在哪里,浏览器都会在它可用时立即执行它,而不会阻塞页面。DOMContentLoaded 在它应该触发的时候触发;无论脚本是否已下载/执行。

第二种方法具有以下优点:

  • 注入脚本标签的脚本可以放置在任何地方,包括文档头部。
  • 该脚本不会阻止渲染。
  • DOMContentLoaded 事件不等待脚本。

第二种方法有以下缺点:

  • 您不能document.write在此类脚本中使用。如果你这样做了,这样的陈述可能会把文档擦干净。
  • 异步执行并不意味着浏览器已经完成了页面的解析。牢记脚本一有可用子句就立即执行。
  • 不保证执行顺序。示例:如果您使用注入的脚本标签加载“library.js”和“use-library.js”,则“use-library.js”可能会在“library.js”之前加载和执行。

说了这么多,还有另一种加载脚本的方法,有三种变体:

<script src="myScript.js" async></script>
<script src="myScript.js" defer></script>
<script src="myScript.js" async defer></script>

关于 Steve Souders 的工作:他提出了 6 种无阻塞加载脚本的技术。HTML5 中引入的async和属性涵盖了Script DOM ElementScript Defer技术,它们的浏览器支持足以让您担心其他技术。defer

于 2014-04-09T08:40:38.753 回答
3

这两种初始化脚本的方式基本相同,但如果可以直接输入结果,就没有理由使用第二种方式。但是,您可以将第二个示例包装在$(document).ready()例如会导致某种延迟加载效果的方法中。这基本上意味着页面将首先加载,然后在页面加载完成后加载脚本。或者,您当然可以创建一个以这种方式初始化某个脚本的方法。当您有一个仅在某些情况下使用的大型脚本时,它很有用。除非您需要它,否则这将阻止加载它,从而减少整体加载时间。

于 2014-03-31T09:43:56.587 回答
2

这不是您问题的直接答案,但无论如何都很好知道。

第二种方法有时用作库后备
例如,您从 Google CDN 加载 jQuery。但是,如果它因任何原因失败,请从您自己的本地副本加载 jQuery。

以下是流行的 HTML5 Boilerplate 建议这样做的方式:

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="js/vendor/jquery-1.11.0.min.js"><\/script>')</script>
于 2014-04-09T05:30:49.450 回答
1

第一种方法意味着脚本标记是硬编码的。第二种方法使用 JavaScript 在页面底部动态添加一个脚本标记。第二种方法的好处是,如果需要修改脚本标签,您可以添加额外的逻辑。也许您可能希望根据文化、浏览器或您可以在 JavaScript 中确定的其他一些因素来加载不同的脚本文件。第二种方法还导致加载 JavaScript 文件而不阻塞网页其余部分的加载。在方法一中,页面将在到达脚本标记时停止加载,加载 JavaScript 文件,然后完成页面其余部分的加载。由于此标签位于页面底部,因此并没有太大的区别。

如果您使用 JavaScript 创建 Windows 应用商店应用程序,则建议使用第一种方法,因为这将允许应用程序对 JavaScript 文件进行字节码缓存,从而使其加载速度更快。

于 2014-03-31T09:46:43.480 回答