$ (documento). già equivalente senza jQuery


2017

Ho uno script che usa $(document).ready, ma non usa nient'altro da jQuery. Vorrei alleggerirlo rimuovendo la dipendenza jQuery.

Come posso implementare la mia $(document).readyfunzionalità senza usare jQuery? So che l'utilizzo window.onloadnon sarà lo stesso, come gli window.onloadincendi dopo che tutte le immagini, i frame, ecc. Sono stati caricati.


296
... e sicuramente non è la stessa funzionalità.
Joel Mueller,

40
Come afferma questa risposta , se tutto ciò che vuoi da jQuery è $(document).ready, puoi risolvere facilmente quel problema eseguendo il tuo codice in fondo alla pagina anziché in alto. HTML5Boilerplate utilizza questo approccio esatto.
Blazemonger,

3
Perché non usare semplicemente DOMContentLoaded? È IE9 + caniuse.com/domcontentloaded developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded
Brock

Ho finalmente chiamato il mio documento e questo ha risolto il mio problema. Quando viene chiamata la funzione, tutto viene caricato.
IgniteCoders

Risposte:


1440

Esiste una sostituzione basata su standard, DOMContentLoadedsupportata da oltre il 98% dei browser , sebbene non IE8:

document.addEventListener("DOMContentLoaded", function(event) { 
  //do work
});

La funzione nativa di jQuery è molto più complicata del semplice window.onload, come illustrato di seguito.

function bindReady(){
    if ( readyBound ) return;
    readyBound = true;

    // Mozilla, Opera and webkit nightlies currently support this event
    if ( document.addEventListener ) {
        // Use the handy event callback
        document.addEventListener( "DOMContentLoaded", function(){
            document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
            jQuery.ready();
        }, false );

    // If IE event model is used
    } else if ( document.attachEvent ) {
        // ensure firing before onload,
        // maybe late but safe also for iframes
        document.attachEvent("onreadystatechange", function(){
            if ( document.readyState === "complete" ) {
                document.detachEvent( "onreadystatechange", arguments.callee );
                jQuery.ready();
            }
        });

        // If IE and not an iframe
        // continually check to see if the document is ready
        if ( document.documentElement.doScroll && window == window.top ) (function(){
            if ( jQuery.isReady ) return;

            try {
                // If IE is used, use the trick by Diego Perini
                // http://javascript.nwbox.com/IEContentLoaded/
                document.documentElement.doScroll("left");
            } catch( error ) {
                setTimeout( arguments.callee, 0 );
                return;
            }

            // and execute any waiting functions
            jQuery.ready();
        })();
    }

    // A fallback to window.onload, that will always work
    jQuery.event.add( window, "load", jQuery.ready );
}

19
Un'implementazione JavaScript pianura effettivo di lavoro qui se qualcuno vuole codice che può solo cadere in: stackoverflow.com/questions/9899372/...
jfriend00

4
Il codice pronto per DOM jQuery sembra essere semplificato: github.com/jquery/jquery/blob/master/src/core/ready.js
Jose Nobile

2
@JoseNobile perché hanno abbandonato il supporto del browser meno
recente

16
Penso che siamo tutti pronti per passare da IE8 ...;). Grazie per il link, @JoseNobile.
Con Antonakos,

13
DOMContentLoaded non funzionerà se lo script viene caricato successivamente. Il documento JQuery pronto viene sempre eseguito.
Jared Insel,

343

Modificare:

Ecco una valida sostituzione per jQuery ready

function ready(callback){
    // in case the document is already rendered
    if (document.readyState!='loading') callback();
    // modern browsers
    else if (document.addEventListener) document.addEventListener('DOMContentLoaded', callback);
    // IE <= 8
    else document.attachEvent('onreadystatechange', function(){
        if (document.readyState=='complete') callback();
    });
}

ready(function(){
    // do something
});

Tratto da https://plainjs.com/javascript/events/running-code-when-the-document-is-ready-15/

Un'altra buona funzione domReady qui presa da https://stackoverflow.com/a/9899701/175071


Dato che la risposta accettata era ben lungi dall'essere completa, ho messo insieme una funzione "pronta" come jQuery.ready()basata sulla fonte jQuery 1.6.2:

var ready = (function(){

    var readyList,
        DOMContentLoaded,
        class2type = {};
        class2type["[object Boolean]"] = "boolean";
        class2type["[object Number]"] = "number";
        class2type["[object String]"] = "string";
        class2type["[object Function]"] = "function";
        class2type["[object Array]"] = "array";
        class2type["[object Date]"] = "date";
        class2type["[object RegExp]"] = "regexp";
        class2type["[object Object]"] = "object";

    var ReadyObj = {
        // Is the DOM ready to be used? Set to true once it occurs.
        isReady: false,
        // A counter to track how many items to wait for before
        // the ready event fires. See #6781
        readyWait: 1,
        // Hold (or release) the ready event
        holdReady: function( hold ) {
            if ( hold ) {
                ReadyObj.readyWait++;
            } else {
                ReadyObj.ready( true );
            }
        },
        // Handle when the DOM is ready
        ready: function( wait ) {
            // Either a released hold or an DOMready/load event and not yet ready
            if ( (wait === true && !--ReadyObj.readyWait) || (wait !== true && !ReadyObj.isReady) ) {
                // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
                if ( !document.body ) {
                    return setTimeout( ReadyObj.ready, 1 );
                }

                // Remember that the DOM is ready
                ReadyObj.isReady = true;
                // If a normal DOM Ready event fired, decrement, and wait if need be
                if ( wait !== true && --ReadyObj.readyWait > 0 ) {
                    return;
                }
                // If there are functions bound, to execute
                readyList.resolveWith( document, [ ReadyObj ] );

                // Trigger any bound ready events
                //if ( ReadyObj.fn.trigger ) {
                //    ReadyObj( document ).trigger( "ready" ).unbind( "ready" );
                //}
            }
        },
        bindReady: function() {
            if ( readyList ) {
                return;
            }
            readyList = ReadyObj._Deferred();

            // Catch cases where $(document).ready() is called after the
            // browser event has already occurred.
            if ( document.readyState === "complete" ) {
                // Handle it asynchronously to allow scripts the opportunity to delay ready
                return setTimeout( ReadyObj.ready, 1 );
            }

            // Mozilla, Opera and webkit nightlies currently support this event
            if ( document.addEventListener ) {
                // Use the handy event callback
                document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
                // A fallback to window.onload, that will always work
                window.addEventListener( "load", ReadyObj.ready, false );

            // If IE event model is used
            } else if ( document.attachEvent ) {
                // ensure firing before onload,
                // maybe late but safe also for iframes
                document.attachEvent( "onreadystatechange", DOMContentLoaded );

                // A fallback to window.onload, that will always work
                window.attachEvent( "onload", ReadyObj.ready );

                // If IE and not a frame
                // continually check to see if the document is ready
                var toplevel = false;

                try {
                    toplevel = window.frameElement == null;
                } catch(e) {}

                if ( document.documentElement.doScroll && toplevel ) {
                    doScrollCheck();
                }
            }
        },
        _Deferred: function() {
            var // callbacks list
                callbacks = [],
                // stored [ context , args ]
                fired,
                // to avoid firing when already doing so
                firing,
                // flag to know if the deferred has been cancelled
                cancelled,
                // the deferred itself
                deferred  = {

                    // done( f1, f2, ...)
                    done: function() {
                        if ( !cancelled ) {
                            var args = arguments,
                                i,
                                length,
                                elem,
                                type,
                                _fired;
                            if ( fired ) {
                                _fired = fired;
                                fired = 0;
                            }
                            for ( i = 0, length = args.length; i < length; i++ ) {
                                elem = args[ i ];
                                type = ReadyObj.type( elem );
                                if ( type === "array" ) {
                                    deferred.done.apply( deferred, elem );
                                } else if ( type === "function" ) {
                                    callbacks.push( elem );
                                }
                            }
                            if ( _fired ) {
                                deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] );
                            }
                        }
                        return this;
                    },

                    // resolve with given context and args
                    resolveWith: function( context, args ) {
                        if ( !cancelled && !fired && !firing ) {
                            // make sure args are available (#8421)
                            args = args || [];
                            firing = 1;
                            try {
                                while( callbacks[ 0 ] ) {
                                    callbacks.shift().apply( context, args );//shifts a callback, and applies it to document
                                }
                            }
                            finally {
                                fired = [ context, args ];
                                firing = 0;
                            }
                        }
                        return this;
                    },

                    // resolve with this as context and given arguments
                    resolve: function() {
                        deferred.resolveWith( this, arguments );
                        return this;
                    },

                    // Has this deferred been resolved?
                    isResolved: function() {
                        return !!( firing || fired );
                    },

                    // Cancel
                    cancel: function() {
                        cancelled = 1;
                        callbacks = [];
                        return this;
                    }
                };

            return deferred;
        },
        type: function( obj ) {
            return obj == null ?
                String( obj ) :
                class2type[ Object.prototype.toString.call(obj) ] || "object";
        }
    }
    // The DOM ready check for Internet Explorer
    function doScrollCheck() {
        if ( ReadyObj.isReady ) {
            return;
        }

        try {
            // If IE is used, use the trick by Diego Perini
            // http://javascript.nwbox.com/IEContentLoaded/
            document.documentElement.doScroll("left");
        } catch(e) {
            setTimeout( doScrollCheck, 1 );
            return;
        }

        // and execute any waiting functions
        ReadyObj.ready();
    }
    // Cleanup functions for the document ready method
    if ( document.addEventListener ) {
        DOMContentLoaded = function() {
            document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
            ReadyObj.ready();
        };

    } else if ( document.attachEvent ) {
        DOMContentLoaded = function() {
            // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
            if ( document.readyState === "complete" ) {
                document.detachEvent( "onreadystatechange", DOMContentLoaded );
                ReadyObj.ready();
            }
        };
    }
    function ready( fn ) {
        // Attach the listeners
        ReadyObj.bindReady();

        var type = ReadyObj.type( fn );

        // Add the callback
        readyList.done( fn );//readyList is result of _Deferred()
    }
    return ready;
})();

Come usare:

<script>
    ready(function(){
        alert('It works!');
    });
    ready(function(){
        alert('Also works!');
    });
</script>

Non sono sicuro di quanto sia funzionale questo codice, ma ha funzionato bene con i miei test superficiali. Ci è voluto un po 'di tempo, quindi spero che tu e gli altri possiate trarne beneficio.

PS .: Suggerisco di compilarlo .

Oppure puoi usare http://dustindiaz.com/smallest-domready-ever :

function r(f){/in/.test(document.readyState)?setTimeout(r,9,f):f()}
r(function(){/*code to run*/});

o la funzione nativa se hai solo bisogno di supportare i nuovi browser (A differenza di jQuery pronto, questo non funzionerà se lo aggiungi dopo che la pagina è stata caricata)

document.addEventListener('DOMContentLoaded',function(){/*fun code to run*/})

14
Alternative @TimoHuovinen: Zepto.js (9,1 kb), Snack.js (8,1 kb), $ dom (2,3 kb) e 140 Medley (0,5 kb). Modifica: puoi anche dare un'occhiata a Ender.
Frederik Krautwald,

2
@FrederikKrautwald $ dom sembra quello che vorrei, ma non sono sicuro che si adatti al conto. Anche Zepto sembra molto promettente, grazie per averlo condiviso!
Timo Huovinen,

@TimoHuovinen Se non hai guardato Ender, dovresti assolutamente dare un'occhiata, enderjs.com .
Frederik Krautwald,

2
@Timo Huovinen: la tua domanda è davvero molto ampia! Quando è stato creato jQuery, ha adattato molti problemi di cross-browser generati da browser che oggi sono meno significativi. Oggi, "solo JavaScript" è più semplice di quanto non fosse. In questo momento, creare un "grande 20kb compresso, che contiene tutto" è stata sicuramente una buona idea per così tanti motivi che preferisco non elencarli tutti.
dotpush,

1
Non mi piace Se le persone preferiscono questa risposta, chiediti perché vuoi eliminare jQuery in primo luogo. È un po 'inutile se hai intenzione di estrarre esattamente la stessa funzionalità con tutto quel fallback del browser gonfiato di nuovo nel tuo bundle. Non è questo il punto principale di evitare jQuery in primo luogo?
Phil

208

Tre opzioni:

  1. Se scriptè l'ultimo tag del corpo, il DOM sarebbe pronto prima dell'esecuzione del tag di script
  2. Quando il DOM è pronto, "readyState" cambierà in "complete"
  3. Metti tutto nel listener di eventi 'DOMContentLoaded'

onreadystatechange

  document.onreadystatechange = function () {
     if (document.readyState == "complete") {
     // document is ready. Do your stuff here
   }
 }

Fonte: MDN

DOMContentLoaded

document.addEventListener('DOMContentLoaded', function() {
   console.log('document is ready. I can sleep now');
});

Preoccupato per i browser dell'età della pietra: vai al codice sorgente di jQuery e usa lareadyfunzione. In quel caso non stai analizzando + eseguendo l'intera libreria che stai facendo solo una piccola parte di essa.


3
Questo secondo esempio è molto più elegante e succinto delle risposte marcate. Perché questo non è stato contrassegnato come quello corretto?
0112

2
Ancora +1 per la cosa DOMContentLoaded, ha fatto esattamente quello che volevo.
Tripleee,

1
onreadystatechange ha fatto il trucco per me ... necessario eseguire alcuni script dopo il caricamento asincrono di jquery.
Abram,

2
Proprio come una FYI, # 1 non è del tutto vero. È possibile che uno script alla fine della pagina venga caricato prima che il DOM sia terminato. Ecco perché gli ascoltatori sono superiori. Ascoltano quando il browser è finito. Metterlo alla fine è incrociare le dita che il caricamento dello script è stato più lento di quanto il browser possa eseguire il rendering.
Machavity,

1
questa variante funzionerà anche al termine del caricamento del documento, si prega di aggiornare la risposta (imo migliore) se è possibile: if (document.readyState == 'complete') {init (); } else {document.onreadystatechange = function () {if (document.readyState == 'complete') {init (); }}}
ZPiDER,

87

Posiziona il tuo <script>/*JavaScript code*/</script>diritto prima del </body> tag di chiusura .

Certo, questo potrebbe non adattarsi agli scopi di tutti poiché richiede la modifica del file HTML anziché semplicemente fare qualcosa nel file JavaScript alla volta document.ready, ma comunque ...


Mi sembra che ci siano stati problemi di compatibilità, come, dal momento che la pagina non è ancora pronta, non puoi fare questo o quello in questi e quei browser. Purtroppo non ricordo più chiaramente. Tuttavia +1 per un modo abbastanza vicino nel 99% di tutti i casi (e suggerito da Yahoo!).
Boldewyn,

7
In realtà, mettere un elemento di script in fondo alla pagina è una soluzione quasi perfetta. Funziona su più browser e simula il documento. Già perfetto. L'unico svantaggio è che è (un po ') più invadente rispetto all'utilizzo di un codice intelligente, dovrai chiedere all'utente dello script che stai creando di aggiungere un frammento di script aggiuntivo per chiamare la tua funzione ready o init.
Stijn de Witt,

@StijndeWitt - Cosa intendi per dover chiamare una funzione init? Uno script che utilizza document. già non ha bisogno di altro codice client per chiamarlo, è autonomo e l'equivalente di quello in cui il codice è incluso alla fine del corpo può anche essere autonomo e non richiede anche un altro codice per chiamarlo.
nnnnnn

1
Perché non inserire lo script dopo il tag body di chiusura e prima del </html>tag di chiusura ?
Charles Holbrow,

1
@CharlesHolbrow Sebbene tutti i browser lo interpretino correttamente, se vuoi che sia html valido, il htmltag dovrebbe contenere solo heade body.
Alvaro Montoro,

66

Povera soluzione dell'uomo:

var checkLoad = function() {   
    document.readyState !== "complete" ? setTimeout(checkLoad, 11) : alert("loaded!");   
};  

checkLoad();  

Visualizza violino

Aggiunto questo, un po 'meglio immagino, portata propria e non ricorsivo

(function(){
    var tId = setInterval(function() {
        if (document.readyState == "complete") onComplete()
    }, 11);
    function onComplete(){
        clearInterval(tId);    
        alert("loaded!");    
    };
})()

Visualizza violino


8
@PhilipLangford O semplicemente inseriscilo all'interno di a setIntervale rimuovi completamente la ricorsione.
Alex W,

1
@Raveren, hmm hai ragione, sono abbastanza sicuro di averlo provato quando l'ho pubblicato. comunque, è diventato ancora più semplice, ora la funzione è appena stata chiamata, nessun avvolgimento.
Jakob Sternberg,

24
Questo non è sexy. No scusa. L'uso di timer / intervalli per rilevare le cose può "funzionare" ma se continui a programmare in questo modo qualsiasi progetto più grande che valga la pena salare si tuffa nel naso. Non hackerare cose insieme in questo modo. Fallo bene. Per favore. Questo tipo di codice danneggia l'ecosistema di sviluppo perché esiste una soluzione migliore e LO SAPETE.
Dudewad,

1
Penso che questa risposta sia molto più vicina a dustindiaz.com/smallest-domready-ever Quindi ho migliorato la sceneggiatura: jsfiddle.net/iegik/PT7x9
iegik

1
@ReidBlomquist Sì, e questo è un modo "sbagliato", ed è quello che sto sottolineando (anche se un po 'categoricamente, lo so). Si potrebbe dire che, facendo qualcosa di sbagliato, si sta in qualche modo "aiutando" l'ecosistema, ma il problema è che con la quantità di codice errato che le persone prendono per codice "buono" perché non hanno l'esperienza per conoscere meglio NON aiuta l'ecosistema, perché poi prenderanno quel codice errato e lo implementeranno in una vera soluzione architettonica di produzione. Quindi, immagino, dovremo solo differire nell'opinione su questo "errore".
Dudewad,

34

Io lo uso questo:

document.addEventListener("DOMContentLoaded", function(event) { 
    //Do work
});

Nota: questo probabilmente funziona solo con i browser più recenti, in particolare questi: http://caniuse.com/#feat=domcontentloaded


13
IE9 e oltre in realtà
Pascalius

Funziona egregiamente anche negli script di contenuto delle estensioni di Chrome se stavi collegando document_start o document_idle event.
Volomike

21

In realtà, se ti interessa solo Internet Explorer 9+ , questo codice sarebbe sufficiente per sostituire jQuery.ready:

    document.addEventListener("DOMContentLoaded", callback);

Se ti preoccupi di Internet Explorer 6 e di alcuni browser davvero strani e rari, funzionerà:

domReady: function (callback) {
    // Mozilla, Opera and WebKit
    if (document.addEventListener) {
        document.addEventListener("DOMContentLoaded", callback, false);
        // If Internet Explorer, the event model is used
    } else if (document.attachEvent) {
        document.attachEvent("onreadystatechange", function() {
            if (document.readyState === "complete" ) {
                callback();
            }
        });
        // A fallback to window.onload, that will always work
    } else {
        var oldOnload = window.onload;
        window.onload = function () {
            oldOnload && oldOnload();
            callback();
        }
    }
},

18

Questa domanda è stata posta molto tempo fa. Per chiunque abbia appena visto questa domanda, ora c'è un sito chiamato "potresti non aver bisogno di jquery" che suddivide - per livello di supporto IE richiesto - tutte le funzionalità di jquery e fornisce alcune librerie alternative più piccole.

Lo script pronto per documenti IE8 secondo te potrebbe non aver bisogno di jquery

function ready(fn) {
    if (document.readyState != 'loading')
        fn();
    else if (document.addEventListener)
        document.addEventListener('DOMContentLoaded', fn);
    else
        document.attachEvent('onreadystatechange', function() {
            if (document.readyState != 'loading')
                fn();
        });
}

Mi chiedo perché 'onreadystatechange'sia necessario piuttosto chedocument.attachEvent('onload', fn);
Luca

13

Recentemente lo stavo usando per un sito mobile. Questa è la versione semplificata di John Resig da "Pro JavaScript Techniques". Dipende da addEvent.

var ready = ( function () {
  function ready( f ) {
    if( ready.done ) return f();

    if( ready.timer ) {
      ready.ready.push(f);
    } else {
      addEvent( window, "load", isDOMReady );
      ready.ready = [ f ];
      ready.timer = setInterval(isDOMReady, 13);
    }
  };

  function isDOMReady() {
    if( ready.done ) return false;

    if( document && document.getElementsByTagName && document.getElementById && document.body ) {
      clearInterval( ready.timer );
      ready.timer = null;
      for( var i = 0; i < ready.ready.length; i++ ) {
        ready.ready[i]();
      }
      ready.ready = null;
      ready.done = true;
    }
  }

  return ready;
})();

13
Fai attenzione con questo codice. NON è equivalente a $ (documento). Già. Questo codice attiva il callback quando document.body è pronto, il che non garantisce che il DOM sia completamente caricato.
Karolis,

12

Cross-browser (anche vecchi browser) e una soluzione semplice:

var docLoaded = setInterval(function () {
    if(document.readyState !== "complete") return;
    clearInterval(docLoaded);

    /*
        Your code goes here i.e. init()
    */
}, 30);

Mostra avviso in jsfiddle


Tranne se ci vogliono più di 30ms per caricare il DOM, il codice non verrà eseguito.
Quelklef,

1
@Quelklef che è impostato Intervallo non impostato Tempo scaduto
Pawel

11

La risposta di jQuery mi è stata molto utile. Con un po 'di refrattarietà si adattava bene alle mie esigenze. Spero che aiuti chiunque altro.

function onReady ( callback ){
    var addListener = document.addEventListener || document.attachEvent,
        removeListener =  document.removeEventListener || document.detachEvent
        eventName = document.addEventListener ? "DOMContentLoaded" : "onreadystatechange"

    addListener.call(document, eventName, function(){
        removeListener( eventName, arguments.callee, false )
        callback()
    }, false )
}

su alcuni browser, removeListenersarà necessario chiamare con il documento come contesto, ad es. removeListener.call(document, ...
Ron,

9

Ecco lo snippet di codice più piccolo per testare DOM pronto che funziona su tutti i browser (anche IE 8):

r(function(){
    alert('DOM Ready!');
});
function r(f){/in/.test(document.readyState)?setTimeout('r('+f+')',9):f()}

Vedere questo risposta .


6

Aggiungilo nella parte inferiore della tua pagina HTML ...

<script>
    Your_Function();
</script>

Perché, i documenti HTML vengono analizzati dall'alto verso il basso.


7
Come fai a sapere che DOM viene creato quando viene eseguito questo codice? Compresi CSS caricati e analizzati? L'API del browser DOMContentLoaded è progettata per questo.
Dan

Dipende davvero da cosa vuole fare con js. Se ha davvero bisogno di eseguire qualcosa quando la pagina è finita o no.
davefrassoni,

5

Vale la pena cercare in Rock Solid addEvent () e http://www.braksator.com/how-to-make-your-own-jquery .

Ecco il codice nel caso in cui il sito non funzioni

function addEvent(obj, type, fn) {
    if (obj.addEventListener) {
        obj.addEventListener(type, fn, false);
        EventCache.add(obj, type, fn);
    }
    else if (obj.attachEvent) {
        obj["e"+type+fn] = fn;
        obj[type+fn] = function() { obj["e"+type+fn]( window.event ); }
        obj.attachEvent( "on"+type, obj[type+fn] );
        EventCache.add(obj, type, fn);
    }
    else {
        obj["on"+type] = obj["e"+type+fn];
    }
}

var EventCache = function(){
    var listEvents = [];
    return {
        listEvents : listEvents,
        add : function(node, sEventName, fHandler){
            listEvents.push(arguments);
        },
        flush : function(){
            var i, item;
            for(i = listEvents.length - 1; i >= 0; i = i - 1){
                item = listEvents[i];
                if(item[0].removeEventListener){
                    item[0].removeEventListener(item[1], item[2], item[3]);
                };
                if(item[1].substring(0, 2) != "on"){
                    item[1] = "on" + item[1];
                };
                if(item[0].detachEvent){
                    item[0].detachEvent(item[1], item[2]);
                };
                item[0][item[1]] = null;
            };
        }
    };
}();

// Usage
addEvent(window, 'unload', EventCache.flush);
addEvent(window, 'load', function(){alert("I'm ready");});

Il secondo collegamento è interrotto.
Peter Mortensen,


4

Questo codice cross-browser chiamerà una funzione quando il DOM è pronto:

var domReady=function(func){
    var scriptText='('+func+')();';
    var scriptElement=document.createElement('script');
    scriptElement.innerText=scriptText;
    document.body.appendChild(scriptElement);
};

Ecco come funziona:

  1. La prima riga domReadychiama il toStringmetodo della funzione per ottenere una rappresentazione in forma di stringa della funzione che si passa e la avvolge in un'espressione che chiama immediatamente la funzione.
  2. Il resto domReadycrea un elemento script con l'espressione e lo aggiunge al bodydocumento.
  3. Il browser esegue i tag di script aggiunti bodydopo che il DOM è pronto.

Ad esempio, se si esegue questa operazione domReady(function(){alert();});:, bodyall'elemento verrà aggiunto quanto segue :

 <script>(function (){alert();})();</script>

Si noti che funziona solo per le funzioni definite dall'utente. Quanto segue non funzionerà:domReady(alert);



3

Che ne dici di questa soluzione?

// other onload attached earlier
window.onload=function() {
   alert('test');
};

tmpPreviousFunction=window.onload ? window.onload : null;

// our onload function
window.onload=function() {
   alert('another message');

   // execute previous one
   if (tmpPreviousFunction) tmpPreviousFunction();
};

3
È possibile utilizzare addEventListener sulla finestra con "load". Gli ascoltatori vengono eseguiti uno dopo l'altro e non è necessario concatenarli manualmente.
Zaffy,

1
Ma il carico è diverso dal pronto. Il "caricamento" avviene anche prima che il documento sia "pronto". Un documento pronto ha il suo DOM caricato, una finestra caricata non ha necessariamente il DOM pronto. Buona risposta però
Mzn

1
@Mzn: penso che sia al contrario. Penso che il documento pronto avvenga prima dell'evento di caricamento della finestra. "In generale, non è necessario attendere che tutte le immagini siano completamente caricate. Se il codice può essere eseguito in precedenza, di solito è meglio inserirlo in un gestore inviato al metodo .ready ()." ( api.jquery.com/load-event )
Tyler Rick,

questo sovrascriverà il resto degli eventi window.onload nella pagina e causerebbe problemi. dovrebbe aggiungere l'evento oltre a quello esistente.
Teoman Shipahi,

L'evento di caricamento può accadere troppo tardi. È doloroso usarlo quando dipende da j / immagini esterne di terze parti ... Un server non responsive che non controlli e tutto fallisce. L'uso di DOMContentLoaded non è solo un'ottimizzazione, è anche più sicuro!
dotpush,

3

È sempre bene usare equivalenti JavaScript rispetto a jQuery. Uno dei motivi è una libreria in meno su cui fare affidamento e sono molto più veloci degli equivalenti jQuery.

Un riferimento fantastico per gli equivalenti di jQuery è http://youmightnotneedjquery.com/ .

Per quanto riguarda la tua domanda, ho preso il codice seguente dal link sopra :) L'unica avvertenza è che funziona solo con Internet Explorer 9 e versioni successive.

function ready(fn) {
    if (document.readyState != 'loading') {
        fn();
    }
    else {
        document.addEventListener('DOMContentLoaded', fn);
    }
}

3

Più minimale e funzionante al 100%

Ho scelto la risposta da PlainJS e funziona bene per me. Si estende in DOMContentLoadedmodo che possa essere accettato su tutti i browser.


Questa funzione è l'equivalente del $(document).ready()metodo di jQuery :

document.addEventListener('DOMContentLoaded', function(){
    // do something
});

Tuttavia, a differenza di jQuery, questo codice verrà eseguito correttamente solo nei browser moderni (IE> 8) e non nel caso in cui il documento sia già reso nel momento in cui questo script viene inserito (ad es. Tramite Ajax). Pertanto, dobbiamo estenderlo un po ':

function run() {
    // do something
}

// in case the document is already rendered
if (document.readyState!='loading') run();
// modern browsers
else if (document.addEventListener) 
document.addEventListener('DOMContentLoaded', run);
// IE <= 8
else document.attachEvent('onreadystatechange', function(){
    if (document.readyState=='complete') run();
});

Questo copre praticamente tutte le possibilità ed è una valida sostituzione dell'helper jQuery.


2

Abbiamo trovato un'implementazione cross-browser rapida e sporca che potrebbe fare il trucco per i casi più semplici con un'implementazione minima:

window.onReady = function onReady(fn){
    document.body ? fn() : setTimeout(function(){ onReady(fn);},50);
};

che cosa doc.body!?
Nabi KAZ,

2

Le soluzioni setTimeout / setInterval qui presentate funzioneranno solo in circostanze specifiche.

Il problema si presenta soprattutto nelle versioni precedenti di Internet Explorer fino alla 8.

Le variabili che influenzano il successo di queste soluzioni setTimeout / setInterval sono:

1) dynamic or static HTML
2) cached or non cached requests
3) size of the complete HTML document
4) chunked or non chunked transfer encoding

il codice originale (Javascript nativo) che risolve questo problema specifico è qui:

https://github.com/dperini/ContentLoaded
http://javascript.nwbox.com/ContentLoaded (test)

questo è il codice da cui il team jQuery ha costruito la propria implementazione.


1

Ecco quello che uso, è veloce e copre tutte le basi che penso; funziona per tutto tranne IE <9.

(() => { function fn() {
    // "On document ready" commands:
    console.log(document.readyState);
};  
  if (document.readyState != 'loading') {fn()}
  else {document.addEventListener('DOMContentLoaded', fn)}
})();

Questo sembra catturare tutti i casi:

  • si attiva immediatamente se il DOM è già pronto (se il DOM non sta "caricando", ma "interattivo" o "completo")
  • se il DOM è ancora in fase di caricamento, imposta un listener di eventi per quando il DOM è disponibile (interattivo).

L'evento DOMContentLoaded è disponibile in IE9 e in tutto il resto, quindi penso personalmente che sia corretto utilizzarlo. Riscrivi la dichiarazione della funzione freccia in una normale funzione anonima se non stai trasferendo il tuo codice da ES2015 a ES5.

Se si desidera attendere il caricamento di tutte le risorse, tutte le immagini visualizzate ecc., Utilizzare invece window.onload.


1

Se non devi supportare browser molto vecchi, ecco un modo per farlo anche quando lo script esterno è caricato con l' attributo asincrono :

HTMLDocument.prototype.ready = new Promise(function(resolve) {
   if(document.readyState != "loading")
      resolve();
   else
      document.addEventListener("DOMContentLoaded", function() {
         resolve();
      });
});

document.ready.then(function() {
   console.log("document.ready");
});

0

Per IE9 +:

function ready(fn) {
  if (document.readyState != 'loading'){
    fn();
  } else {
    document.addEventListener('DOMContentLoaded', fn);
  }
}

0

Se stai caricando jQuery nella parte inferiore di BODY, ma stai riscontrando problemi con il codice che scrive jQuery (<func>) o jQuery (documento) .ready (<func>), controlla jqShim su Github.

Invece di ricreare la propria funzione pronta per il documento, mantiene semplicemente le funzioni fino a quando non è disponibile jQuery, quindi procede con jQuery come previsto. Lo scopo di spostare jQuery nella parte inferiore del corpo è accelerare il caricamento della pagina e puoi ancora realizzarlo incorporando jqShim.min.js nella parte superiore del modello.

Ho finito per scrivere questo codice per spostare tutti gli script di WordPress nel piè di pagina, e solo questo codice shim ora si trova direttamente nell'intestazione.


0

Prova questo:

function ready(callback){
    if(typeof callback === "function"){
        document.addEventListener("DOMContentLoaded", callback);
        window.addEventListener("load", callback);
    }else{
        throw new Error("Sorry, I can not run this!");
    }
}
ready(function(){
    console.log("It worked!");
});

Lol eseguirai il callback due volte
Andrew

0
function onDocReady(fn){ 
    $d.readyState!=="loading" ? fn():document.addEventListener('DOMContentLoaded',fn);
}

function onWinLoad(fn){
    $d.readyState==="complete") ? fn(): window.addEventListener('load',fn);
} 

onDocReady fornisce un callback quando la dom HTML è pronta per accedere / analizzare / manipolare completamente.

onWinLoad fornisce una richiamata quando tutto è stato caricato (immagini, ecc.)

  • Queste funzioni possono essere richiamate quando vuoi.
  • Supporta più "ascoltatori".
  • Funzionerà con qualsiasi browser.

0
(function(f){
  if(document.readyState != "loading") f();
  else document.addEventListener("DOMContentLoaded", f);
})(function(){
  console.log("The Document is ready");
});

Cosa aggiunge questo che le altre risposte no?
dwjohnston,

Utilizza una chiusura autonoma (non popola l'ambito globale della "finestra"), funziona su tutti i browser ed è molto compatto. Non vedo altre risposte simili.
Dustin Poissant,

Funziona anche dopo che il DOM è già stato caricato (come jQuery.ready), cosa che la maggior parte di queste risposte non riesce.
Dustin Poissant,

0

La maggior parte delle funzioni vanilla di JS Ready NON considera lo scenario in cui DOMContentLoadedè impostato il gestore dopo che il documento è già stato caricato - Il che significa che la funzione non verrà mai eseguita . Questo può accadere se cerchi DOMContentLoadedall'interno di uno asyncscript esterno ( <script async src="file.js"></script>).

Il codice seguente controlla DOMContentLoadedsolo se il documento readyStatenon è già interactiveo complete.

var DOMReady = function(callback) {
  document.readyState === "interactive" || document.readyState === "complete" ? callback() : document.addEventListener("DOMContentLoaded", callback());
};
DOMReady(function() {
  //DOM ready!
});

Se vuoi supportare anche IE:

var DOMReady = function(callback) {
    if (document.readyState === "interactive" || document.readyState === "complete") {
        callback();
    } else if (document.addEventListener) {
        document.addEventListener('DOMContentLoaded', callback());
    } else if (document.attachEvent) {
        document.attachEvent('onreadystatechange', function() {
            if (document.readyState != 'loading') {
                callback();
            }
        });
    }
};

DOMReady(function() {
  // DOM ready!
});

0

Uso semplicemente:

setTimeout(function(){
    //reference/manipulate DOM here
});

E a differenza document.addEventListener("DOMContentLoaded" //etcdella risposta più in alto, funziona fino a IE9 - http://caniuse.com/#search=DOMContentLoaded indica solo IE11.

È interessante notare che mi sono imbattuto in questa setTimeoutsoluzione nel 2009: il controllo della disponibilità del DOM è eccessivo? , che probabilmente avrebbe potuto essere formulato in modo leggermente migliore, poiché intendevo "è eccessivo utilizzare approcci più complicati di vari framework per verificare la prontezza del DOM".

La mia migliore spiegazione del perché questa tecnica funziona è che, quando è stato raggiunto lo script con un setTimeout, il DOM è in fase di analisi, quindi l'esecuzione del codice all'interno di setTimeout viene rinviata fino al termine dell'operazione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.