可以推迟加载jQuery吗?

Kev*_*ice 66 javascript jquery pagespeed

让我们面对现实吧,jQuery/jQuery-ui是一个重载下载.

Google建议延迟加载JavaScript以加快初始呈现速度.我的页面使用jQuery来设置一些位于页面下方的选项卡(主要是在初始视图之外),我想将jQuery推迟到页面呈现之后.

Google的延迟代码在页面加载后通过挂钩到正文onLoad事件为DOM添加标记:

<script type="text/javascript">

 // Add a script element as a child of the body
 function downloadJSAtOnload() {
 var element = document.createElement("script");
 element.src = "deferredfunctions.js";
 document.body.appendChild(element);
 }

 // Check for browser support of event handling capability
 if (window.addEventListener)
 window.addEventListener("load", downloadJSAtOnload, false);
 else if (window.attachEvent)
 window.attachEvent("onload", downloadJSAtOnload);
 else window.onload = downloadJSAtOnload;

</script>
Run Code Online (Sandbox Code Playgroud)

我想以这种方式推迟加载jQuery,但是当我尝试它时,我的jQuery代码无法找到jQuery(我不是完全出乎意料):

$(document).ready(function() {
    $("#tabs").tabs();
});
Run Code Online (Sandbox Code Playgroud)

所以,似乎我需要找到一种方法来推迟执行jQuery代码,直到加载jQuery.如何检测添加的标签是否已完成加载和解析?

作为推论,似乎异步加载也可能包含答案.

有什么想法吗?

amp*_*and 52

试试这个,这是我之前从jQuerify bookmarklet编辑的.我经常使用它来加载jQuery并在加载后执行它们.你当然可以用你自己的url替换那里的url到你的自定义jquery.

(function() {
      function getScript(url,success){
        var script=document.createElement('script');
        script.src=url;
        var head=document.getElementsByTagName('head')[0],
            done=false;
        script.onload=script.onreadystatechange = function(){
          if ( !done && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete') ) {
            done=true;
            success();
            script.onload = script.onreadystatechange = null;
            head.removeChild(script);
          }
        };
        head.appendChild(script);
      }
        getScript('http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js',function(){
            // YOUR CODE GOES HERE AND IS EXECUTED AFTER JQUERY LOADS
        });
    })();
Run Code Online (Sandbox Code Playgroud)

我真的会将jQuery和jQuery-UI合并到一个文件中,然后使用url.如果您真的想单独加载它们,只需链接getScripts:

getScript('http://myurltojquery.js',function(){
        getScript('http://myurltojqueryUI.js',function(){
              //your tab code here
        })
});
Run Code Online (Sandbox Code Playgroud)

  • 我用这个非常成功.我还将第10行的`success();`修改为`if(success && getClass.call(success)=='[object Function]'){success(); }`.如果它不是null并且它是一个函数,则仅执行**成功函数**.这允许您在没有函数调用的情况下调用`getScript("myScript.js")`. (5认同)

Pev*_*awi 14

由于这是一个关于一个重要主题的排名靠前的问题,让我如此大胆地根据@valmarv和@amparsand之前的回答提供我自己的看法.

我正在使用多维数组来加载脚本.将那些之间没有依赖关系的组合在一起:

var dfLoadStatus = 0;
var dfLoadFiles = [
      ["http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"],
      ["http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/jquery-ui.min.js",
       "/js/somespecial.js",
       "/js/feedback-widget.js#2312195",
       "/js/nohover.js"]
     ];

function downloadJSAtOnload() {
    if (!dfLoadFiles.length) return;

    var dfGroup = dfLoadFiles.shift();
    dfLoadStatus = 0;

    for(var i = 0; i<dfGroup.length; i++) {
        dfLoadStatus++;
        var element = document.createElement('script');
        element.src = dfGroup[i];
        element.onload = element.onreadystatechange = function() {
        if ( ! this.readyState || 
               this.readyState == 'complete') {
            dfLoadStatus--;
            if (dfLoadStatus==0) downloadJSAtOnload();
        }
    };
    document.body.appendChild(element);
  }

}

if (window.addEventListener)
    window.addEventListener("load", downloadJSAtOnload, false);
else if (window.attachEvent)
    window.attachEvent("onload", downloadJSAtOnload);
else window.onload = downloadJSAtOnload;
Run Code Online (Sandbox Code Playgroud)

它在加载后加载第一个jquery,它会立即加载其他脚本.您可以通过在页面的任何位置添加到阵列来轻松添加脚本:

dfLoadFiles.push(["/js/loadbeforeA.js"]);
dfLoadFiles.push(["/js/javascriptA.js", "/js/javascriptB.js"]);
dfLoadFiles.push(["/js/loadafterB.js"]);
Run Code Online (Sandbox Code Playgroud)


GKi*_*lin 8

这里是对异步/延迟javascript加载现代方法的一个很好的描述.但它不适用于内联脚本

<script type="text/javascript" src="/jquery/3.1.1-1/jquery.min.js" defer></script>
<script type="text/javascript" defer>
    $(function () {   //  <- jquery is not yet initialized
      ...
    });
</script>
Run Code Online (Sandbox Code Playgroud)

@nilskp - externalize脚本建议了最简单的异步加载解决方案:

<script type="text/javascript" src="/jquery/3.1.1-1/jquery.min.js" defer></script>
<script type="text/javascript" src="resources/js/onload.js" defer></script>
Run Code Online (Sandbox Code Playgroud)


asi*_*iop 5

我在 async/defered jquery 脚本标记之后添加了这段代码,这定义了一个临时函数 $ ,它将累积所有加载完成后需要运行的内容,然后一旦我们完成,此时就使用 $ 。将被覆盖以执行函数。使用这段代码,无需进一步更改文档中的 jQuery onload 语法。

<script defer async src="https://code.jquery.com/jquery-2.2.0.min.js">
<script>
    var executeLater = [];
    function $(func) {
        executeLater.push(func);
    }
    window.addEventListener('load', function () {
        $(function () {
            for (var c = 0; c < executeLater.length; c++) {
                executeLater[c]();
            }
        });
    })
</script>
Run Code Online (Sandbox Code Playgroud)

....进而...

<script>
    $(function() {
        alert("loaded");
    });
</script>
Run Code Online (Sandbox Code Playgroud)