推迟内联JavaScript执行?

17
在我的网站上,我有许多内联JavaScript片段。其中大部分需要jQuery和类似的东西。
但是我想将jQuery的加载推迟到页面呈现之后。这意味着,在加载jQuery之前,我的内联JavaScript将被执行。我能做些什么吗?我正在寻找易于实现的解决方案(由于我的内联JavaScript是在为用户准备页面时自动生成的,因此也无法移动它)。

你能举个inline的例子吗?是指实际上在HTML元素内部吗?还是指每个都在自己的<script>中? - Lix
另外,听起来你对JavaScript有控制权(因为你与jQuery执行顺序发生了冲突)。我怀疑这可以通过另一种方式解决... - Dane O'Connor
2个回答

11

如果您能将JavaScript放在文档末尾,效果会更好。在源代码中添加小的内联JavaScript代码会降低页面性能。

话虽如此,您可以创建一个数组并将函数推入该数组。然后,在页面末尾,在加载jQuery之后,循环遍历该数组并执行每个函数。

例如:

<html>
  ...
  <script>window.loadEvents = [];</script>
  ...
  <script>loadEvents.push(function() { alert("inline code here"); });</script>
  ...
  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
  <script>$.each(loadEvents, function(_,f) { f(); });</script>
</html>

然而 - 如我所说 - 最好将所有脚本元素推到页面底部,而不是在HTML和JavaScript之间来回切换。如果这样做,呈现性能将会严重降低。


你能举个例子吗? :D - Geniusknight
对我来说,我必须向回调函数添加第二个参数,它保存实际值而不是索引...例如: <script>$.each(loadEvents, function(i, f) { f(); });</script> - D.Tate

8
您可以通过将内联脚本的type设置为浏览器不会处理的类型,例如text/example来模拟延迟。然后在文档末尾克隆这些脚本,并将它们替换为text/javascript
处理所有text/examples的代码非常简单:
window.addEventListener("load", function() {

    var arr = document.querySelectorAll("script[type='text/example']");
    for (var x = 0; x < arr.length; x++) {
        var cln = arr[x].cloneNode(true);
        cln.type = "text/javascript";
        document.querySelectorAll("body")[0].appendChild(cln);
    }

});

如果您偏好使用jQuery(您将需要在包含jQuery文件之后添加此脚本):

$(function() {
    $("script[type='text/example']").each(function() {
        $(this).clone().attr("type","text/javascript").appendTo("body"); 
    });
});

这段代码会等待页面加载完毕后,选择所有类型为text/example的脚本,并将它们复制到body的末尾,类型为text/javascript,以便正常执行。

例如:

...
<script type="text/example">
    console.log("I am before the h1");
</script>

<h1>Page Title</h1>

<script type="text/javascript">
    console.log("I am after the h1");
</script>
...

在控制台中将会看到以下信息:

我在h1标签之后

我在h1标签之前

您可以在此JSFiddle上查看实际演示:http://jsfiddle.net/rqckwc79/


该解决方案的优点:

  • 它是跨浏览器的解决方案。
  • 代码是有效的HTML/JavaScript。
  • 它适用于严格模式。

该解决方案的缺点:

  • 您需要控制内联脚本以更改“type”。
  • 如troelskn所说,性能比将所有代码移到底部要差(但我了解有些情况下可能不可能)。
  • 它无法在旧版本的IE上工作(尽管可以修改代码以支持它们)。

我知道我对这个问题有点晚了,但我看到其他用户提出了相关问题并被引用到这里。所以他们有另一个选择,不需要更改页眉/页脚来延迟内联脚本。 - Alvaro Montoro
1
这是一个非常好的解决方案,特别是在 Pagespeed 友好的方式下推迟 JavaScript。谢谢。你所说的旧版 IE,是指低于 8 版本的吗?! - ObiHill
是的。这个解决方案使用了 querySelectorAll,它只支持 IE 8 及以上版本(对于特定版本仅部分支持)。我还有一个版本,可以在 IE 6 和 7 上运行,但它更复杂(并且有点“hacky”)。 - Alvaro Montoro
我明白了。IE8是我的当前基线;如果你再低一点,那简直就是痛苦。 - ObiHill

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