Domanda

Ammettiamolo, JQuery/JQuery-Ui è un download pesante.

Google consiglia Caricamento differito di JavaScript Per accelerare il rendering iniziale. La mia pagina utilizza jQuery per impostare alcune schede che sono posizionate in basso nella pagina (principalmente fuori dalla vista iniziale) e vorrei differire jQuery fino a quando la pagina non si è resa.

Il codice di differimento di Google aggiunge un tag al DOM dopo che la pagina si carica agganciando all'evento del corpo Onload:

<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>

Vorrei differire il caricamento di jQuery in questo modo, ma quando l'ho provato il mio codice jQuery non è riuscito a trovare jQuery (non completamente inaspettato da parte mia):

$(document).ready(function() {
    $("#tabs").tabs();
});

Quindi, sembra che ho bisogno di trovare un modo per rinviare l'esecuzione del mio codice jQuery fino a quando non viene caricato jQuery. Come posso rilevare che il tag aggiunto ha terminato il caricamento e l'analisi?

Come corollario, sembra che Caricamento asincrono può anche contenere una risposta.

qualche idea?

È stato utile?

Soluzione

Prova questo, che è qualcosa che ho modificato qualche tempo fa dal bookmarklet Jquerify. Lo uso spesso per caricare jQuery ed eseguire cose dopo il caricamento. Ovviamente puoi sostituire l'URL lì con il tuo URL alla tua jQuery personalizzata.

(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
        });
    })();

Combinerei davvero JQuery e JQuery-UI in un file e userei un URL. Se volevi davvero caricarli separatamente, basta incazzare i getscripts:

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

Altri suggerimenti

Dato che questa è una domanda di alto livello su un argomento importante, lasciami essere così audace da fornire la mia opinione in base a una risposta precedente di @valmarv e @amprsand.

Sto usando un array multidimensionale per caricare gli script. Raggruppando quelli che non hanno dipendenze tra di loro:

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;

Carica la prima jQuery dopo che è stato caricato, continua a caricare gli altri script contemporaneamente. Puoi aggiungere facilmente gli script aggiungendo all'array ovunque sulla tua pagina:

dfLoadFiles.push(["/js/loadbeforeA.js"]);
dfLoadFiles.push(["/js/javascriptA.js", "/js/javascriptB.js"]);
dfLoadFiles.push(["/js/loadafterB.js"]);

Ecco una buona descrizione di Approccio moderno per il caricamento asincrone/Defer JavaScript. Ma non funziona per gli script in linea

<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>

La soluzione più semplice per il caricamento asincrone è stata suggerita da @Nilskp - Externalize Script:

<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>

Metti jQuery e il tuo codice dipendente da jQuery alla fine del file HTML.

EDIT: un po 'più chiaro

<html>
<head></head>
<body>
    <!-- Your normal content here -->
    <script type="text/javascript" src="http://path/to/jquery/jquery.min.js"></script>
    <script>//Put your jQuery code here</script>
</body>
</html>
element.addEventListener("load", function () {
    $('#tabs').tabs()
}, false);

Prova questo.

In una certa situazione potresti licenziare un evento quando viene caricato jQuery.

<script type="text/javascript">
    (function (window) {

        window.jQueryHasLoaded = false;

        document.body.addEventListener('jqueryloaded', function (e) {
            console.log('jqueryloaded ' + new Date() );
        }, false);

        function appendScript(script) {
            var tagS = document.createElement("script"), 
                s = document.getElementsByTagName("script")[0];
            tagS.src = script.src;
            s.parentNode.insertBefore(tagS, s);

            if ( script.id == 'jquery' ) {
                tagS.addEventListener('load', function (e) {
                    window.jQueryHasLoaded = true;
                    var jQueryLoaded = new Event('jqueryloaded');
                    document.body.dispatchEvent(jQueryLoaded);
                }, false);
            }
        }

        var scripts = [
            {
                'id': 'jquery',
                'src': 'js/libs/jquery/jquery-2.0.3.min.js'
            },
            {
                'src': 'js/myscript1.js'
            },
            {
                'src': 'js/myscript2.js'
            }
        ];

        for (var i=0; i < scripts.length; i++) {
            appendScript(scripts[i]);
        }

    }(window));
</script>

Quindi avvolgi le tue dipendenze in una funzione:

// myscript1.js 
(function(){ 

    function initMyjQueryDependency() {
        console.log('my code is executed after jquery is loaded!');
        // here my code that depends on jquery
    }

    if ( jQueryHasLoaded === true )
        initMyjQueryDependency();
    else
        document.body.addEventListener('jqueryloaded', initMyjQueryDependency, false);

}());

Se JQuery termina per caricare dopo gli altri script, le tue dipendenze verranno eseguite quando viene licenziato l'evento caricato JQuery.

Se JQuery è già caricato, jQueryHasLoaded === true, la tua dipendenza verrà eseguita initMyjQueryDependency().

Aggiungo questo pezzo di codice dopo il tag di script jQuery asincrone/differito, questo definisce una funzione temporanea $ che accumulerà tutto ciò che deve essere eseguito quando tutto è stato fatto caricamento, e quindi una volta che abbiamo finito di usare $ che a questo punto sarebbe sovrascritto per eseguire le funzioni. Con questo pezzo di codice non è necessario modificare la sintassi di jQuery Onload più in basso nel documento.

<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>

....poi...

<script>
    $(function() {
        alert("loaded");
    });
</script>

Beh, mi sembra, tutto ciò che devi fare è a) Aggiungi il codice jQuery che si desidera eseguire su carico, fino alla fine del file jQuery o b) Aggiungi al downloadJSAtOnload funzione così:

<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);
 $("#tabs").tabs(); // <==== NOTE THIS. This should theoretically run after the
                    // script has been appended, though you'll have to test this
                    // because I don't know if the JavaScript above will wait for
                    // the script to load before continuing
 }

 // 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>

Il seguente codice dovrebbe caricare gli script dopo il termine della finestra:

<html>
<head>
    <script>
    var jQueryLoaded = false;
    function test() {
        var myScript = document.createElement('script');
        myScript.type = 'text/javascript';
        myScript.async = true;
        myScript.src = jQueryLoaded ? 'http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.js' : 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/jquery-ui.min.js';
        document.body.appendChild(myScript);

        if(!jQueryLoaded){
            alert('jquery was loaded');
            jQueryLoaded = true;
            test();
        } else {
            alert('jqueryui was loaded');   
        }
    }

    if (window.addEventListener){
        alert('window.addEventListener');
        window.addEventListener("load", test, false);
    } else if (window.attachEvent){
        alert('window.attachEvent');
        window.attachEvent("onload", test);
    } else{
        alert('window.onload');
        window.onload = test;
    }
    </script>
</head>
<body>
<p>Placeholder text goes here</p>
</body>
</html>

Ha lavorato per me in Chrome, FF e IE9 - fammi sapere se questo aiuta

Ecco la mia versione che supporta il concatenamento per assicurarsi che gli script siano caricati uno dopo l'altro, in base a ampersandCodice:

var deferredJSFiles = ['jquery/jquery', 'file1', 'file2', 'file3'];
function downloadJSAtOnload() {
    if (!deferredJSFiles.length)
        return;
    var deferredJSFile = deferredJSFiles.shift();
    var element = document.createElement('script');
    element.src = deferredJSFile.indexOf('http') == 0 ? deferredJSFile : '/js/' + deferredJSFile + '.js';
    element.onload = element.onreadystatechange = function() {
        if (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete')
            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;
<!doctype html>
<html>
    <head>

    </head>
    <body>
        <p>If you click on the "Hide" button, I will disappear.</p>
        <button id="hide" >Hide</button>
        <button id="show" >Show</button>

        <script type="text/javascript">
            function loadScript(url, callback) {

                var script = document.createElement("script")
                script.type = "text/javascript";

                if (script.readyState) {  //IE
                    script.onreadystatechange = function() {
                        if (script.readyState == "loaded" ||
                                script.readyState == "complete") {
                            script.onreadystatechange = null;
                            callback();
                        }
                    };
                } else {  //Others
                    script.onload = function() {
                        callback();
                    };
                }

                script.src = url;
                document.body.appendChild(script);
            }
            loadScript("http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js",
                    function() {
                        //YAHOO.namespace("mystuff");
                        $("#show").click(function() {
                            $("p").show();
                        });
                        $("#hide").click(function() {
                            $("p").hide();
                        });

                        //more...
                    });
        </script>

    </body>
</html>

Penso che modernizr.load () merita una menzione qui - gestisce il caricamento della dipendenza molto bene

Sembra che tu abbia solo bisogno <script defer> : http://www.w3schools.com/tags/att_script_defer.asp

Guarda jQuery.holdReady()

"Tiene o rilascia l'esecuzione dell'evento pronto di JQuery." (JQuery 1.6+)

http://api.jquery.com/jquery.holdready/

Carica tutti gli script alla fine di HTML con http://labjs.com, è una soluzione al 100% e l'ho testata molte volte contro le regole GTMetrix. esempio http://gtmetrix.com/reports/interactio.cz/jxomhslv

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top