$ (Dokument). bereits gleichwertig ohne jQuery

2017

Ich habe ein Skript, das verwendet $(document).ready, aber es verwendet nichts anderes von jQuery. Ich möchte es aufhellen, indem ich die jQuery-Abhängigkeit entferne.

Wie kann ich meine eigenen $(document).readyFunktionen implementieren, ohne jQuery zu verwenden? Ich weiß, dass die Verwendung window.onloadnicht mit window.onloadBränden identisch ist, nachdem alle Bilder, Frames usw. geladen wurden.

FlySwat
quelle
296
... und auch definitiv nicht die gleiche Funktionalität.
Joel Mueller
40
Wie in dieser Antwort angegeben$(document).ready , können Sie dieses Problem leicht lösen , wenn Sie von jQuery alles wollen , indem Sie Ihren Code ganz unten auf der Seite anstatt oben ausführen. HTML5Boilerplate verwendet genau diesen Ansatz.
Blazemonger
3
Warum nicht einfach DOMContentLoaded verwenden? Es ist IE9 + caniuse.com/domcontentloaded developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded
Brock
Ich habe meinen Anruf am Ende des Dokuments getätigt und das löst mein Problem. Wenn die Funktion aufgerufen wird, wird alles geladen.
IgniteCoders

Antworten:

1440

Es gibt einen standardbasierten Ersatz, DOMContentLoadedder von über 98% der Browser unterstützt wird , jedoch nicht von IE8:

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

Die native Funktion von jQuery ist viel komplizierter als nur window.onload, wie unten dargestellt.

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 );
}
Chad Grant
quelle
19
Eine tatsächlich funktionierende einfache Javascript-Implementierung hier, wenn jemand Code möchte, kann er einfach vorbeischauen
jfriend00
4
jQuery DOM-fähiger Code scheint vereinfacht zu sein: github.com/jquery/jquery/blob/master/src/core/ready.js
Jose Nobile
2
@ JoseNobile, weil sie ältere Browser-Unterstützung eingestellt haben
huysentruitw
16
Ich denke, wir sind alle bereit, von IE8 fortzufahren ...;). Danke für den Link, @JoseNobile.
Con Antonakos
13
DOMContentLoaded funktioniert nicht, wenn das Skript anschließend geladen wird. JQuery-Dokument bereit wird immer ausgeführt.
Jared Insel
343

Bearbeiten:

Hier ist ein praktikabler Ersatz für jQuery bereit

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

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

Eine weitere gute domReady-Funktion stammt von https://stackoverflow.com/a/9899701/175071


Da die akzeptierte Antwort bei weitem nicht vollständig war, habe ich eine "Bereit" -Funktion wie auf der jQuery.ready()Basis von jQuery 1.6.2 zusammengefügt:

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

Wie benutzt man:

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

Ich bin nicht sicher, wie funktional dieser Code ist, aber er hat bei meinen oberflächlichen Tests gut funktioniert. Das hat eine ganze Weile gedauert, also hoffe ich, dass Sie und andere davon profitieren können.

PS.: Ich schlage vor , es zu kompilieren .

Oder Sie können http://dustindiaz.com/smallest-domready-ever verwenden :

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

oder die native Funktion, wenn Sie nur die neuen Browser unterstützen müssen (Im Gegensatz zu jQuery ready wird diese nicht ausgeführt, wenn Sie diese nach dem Laden der Seite hinzufügen).

document.addEventListener('DOMContentLoaded',function(){/*fun code to run*/})
Timo Huovinen
quelle
14
@ TimoHuovinen-Alternativen: Zepto.js (9,1 kb), Snack.js (8,1 kb), $ dom (2,3 kb) und 140 Medley (0,5 kb). Edit: Sie können sich auch Ender ansehen.
Frederik Krautwald
2
@FrederikKrautwald $ dom klingt wie das, was ich möchte, aber nicht sicher, ob es die Rechnung passt. Zepto sieht auch sehr vielversprechend aus, danke fürs Teilen!
Timo Huovinen
@ TimoHuovinen Wenn Sie Ender nicht angesehen haben, sollten Sie auf jeden Fall einen Blick darauf werfen, enderjs.com .
Frederik Krautwald
2
@ Timo Huovinen: Ihre Frage ist wirklich sehr, sehr weit gefasst! Als jQuery erstellt wurde, wurden viele browserübergreifende Probleme behoben, die von Browsern verursacht wurden, die heute weniger wichtig sind. Heute ist "nur Javascript" einfacher als früher. Zu diesem Zeitpunkt war es sicherlich aus so vielen Gründen eine gute Idee, ein "großes komprimiertes 20-KB-Format zu erstellen, das alles enthält", dass ich es vorziehe, nicht alle aufzulisten.
Dotpush
1
Das gefällt mir nicht. Wenn die Leute diese Antwort bevorzugen, fragen Sie sich, warum Sie jQuery überhaupt löschen möchten. Es ist ein bisschen sinnlos, wenn Sie nur die exakt gleiche Funktionalität mit all dem Browser-Fallback extrahieren, der wieder in Ihr Bundle aufbläht. Ist das nicht der springende Punkt, um jQuery überhaupt zu vermeiden?
Phil
208

Drei Optionen:

  1. Wenn scriptes sich um das letzte Tag des Körpers handelt, ist das DOM bereit, bevor das Skript-Tag ausgeführt wird
  2. Wenn das DOM bereit ist, ändert sich "readyState" in "complete".
  3. Fügen Sie alles unter den Ereignis-Listener 'DOMContentLoaded' ein

onreadystatechange

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

Quelle: MDN

DOMContentLoaded

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

Besorgt über steinzeitliche Browser: Gehen Sie zum jQuery-Quellcode und verwenden Sie diereadyFunktion. In diesem Fall analysieren und führen Sie nicht die gesamte Bibliothek aus, sondern nur einen sehr kleinen Teil davon.

Jhankar Mahbub
quelle
3
Dieses zweite Beispiel ist viel eleganter und prägnanter als die markierten Antworten. Warum wurde dieser nicht als der richtige markiert?
0112
2
Immer noch +1 für das DOMContentLoaded-Ding, es hat genau das getan, was ich wollte.
Tripleee
1
onreadystatechange hat den Trick für mich gemacht ... musste nach dem Laden der asynchronen JQuery ein Skript ausführen.
Abram
2
Genau wie zu Ihrer Information ist # 1 nicht ganz richtig. Es ist durchaus möglich, dass ein Skript am Ende der Seite geladen wird, bevor das DOM fertig ist. Deshalb sind die Zuhörer überlegen. Sie warten darauf, wann der Browser fertig ist. Wenn Sie es am Ende setzen, drücken Sie die Daumen, dass das Laden des Skripts langsamer war, als der Browser rendern kann.
Machavity
1
Diese Variante funktioniert auch, wenn das Laden des Dokuments bereits abgeschlossen ist. Bitte aktualisieren Sie Ihre (imo beste) Antwort, wenn Sie können: if (document.readyState == 'complete') {init (); } else {document.onreadystatechange = function () {if (document.readyState == 'complete') {init (); }}}
ZPiDER
87

Platzieren Sie Ihr <script>/*JavaScript code*/</script>Recht vor dem schließenden </body> Tag.

Zugegeben, dies ist möglicherweise nicht für alle Zwecke geeignet, da die HTML-Datei geändert werden muss, anstatt nur etwas in der JavaScript-Datei a la zu tun document.ready, aber dennoch ...

rauben
quelle
Es scheint mir, dass es Kompatibilitätsprobleme gab. Da die Seite noch nicht fertig ist, können Sie dies oder jenes in diesen und jenen Browsern nicht tun. Leider kann ich mich nicht klarer erinnern. Trotzdem +1 für einen Weg, der in 99% aller Fälle nah genug ist (und von Yahoo! vorgeschlagen wird).
Boldewyn
7
Das Einfügen eines Skriptelements am Ende der Seite ist eine nahezu perfekte Lösung. Es funktioniert browserübergreifend und simuliert document.ready perfect. Der einzige Nachteil ist, dass es (etwas) aufdringlicher ist als die Verwendung von Smart Code. Sie müssen den Benutzer des von Ihnen erstellten Skripts bitten, ein zusätzliches Skriptfragment hinzuzufügen, um Ihre Ready- oder Init-Funktion aufzurufen.
Stijn de Witt
@StijndeWitt - Was meinst du damit, eine Init-Funktion aufrufen zu müssen? Ein Skript, das document.ready verwendet, benötigt keinen anderen Client-Code, um es aufzurufen. Es ist in sich geschlossen, und das Äquivalent zu dem, in dem der Code am Ende des Körpers enthalten ist, kann auch in sich geschlossen sein und nicht benötigen einen anderen Code, um ihn aufzurufen.
nnnnnn
1
Warum nicht das Skript nach dem schließenden Body-Tag und vor dem schließenden </html>Tag einfügen?
Charles Holbrow
1
@CharlesHolbrow Obwohl alle Browser es korrekt interpretieren, sollte das htmlTag nur headund enthalten , wenn Sie möchten, dass es ein gültiges HTML ist body.
Alvaro Montoro
66

Die Lösung des armen Mannes:

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

checkLoad();  

Geige anzeigen

Fügte dieses hinzu, ein bisschen besser, denke ich, eigener Umfang und nicht rekursiv

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

Geige anzeigen

Jakob Sternberg
quelle
8
@PhilipLangford Oder legen Sie es einfach in ein setIntervalund entfernen Sie die Rekursion vollständig.
Alex W
1
@ Raveren, hmm du hast recht, ich bin mir ziemlich sicher, dass ich es getestet habe, als ich es gepostet habe. sowieso wurde es nur noch einfacher, jetzt wird die Funktion einfach aufgerufen, kein Wrapping.
Jakob Sternberg
24
Das ist nicht sexy. Nein Entschuldigung. Die Verwendung von Timern / Intervallen zum Erkennen von Dingen kann "funktionieren", aber wenn Sie so weiter programmieren, wird jedes größere Projekt, das sein Geld wert ist, in die Nase springen. Hacke solche Sachen nicht zusammen. Mach es richtig. Bitte. Diese Art von Code schadet dem Entwicklungs-Ökosystem, weil es eine bessere Lösung gibt und Sie es wissen.
Dudewad
1
Ich denke, diese Antwort kommt Dustindiaz.com/smallest-domready-ever viel näher. Also habe ich das Skript verbessert: jsfiddle.net/iegik/PT7x9
iegik
1
@ReidBlomquist Ja, und das ist ein "falscher" Weg, und darauf weise ich hin (wenn auch etwas hartnäckig, ich weiß). Man könnte sagen, dass es das Ökosystem irgendwie "hilft", wenn man es falsch macht, aber das Problem ist, dass die Leute mit der Menge an schlechtem Code "guten" Code nehmen, weil sie nicht die Erfahrung haben, es besser zu wissen hilft dem Ökosystem NICHT, denn dann werden sie diesen schlechten Code nehmen und ihn in eine tatsächliche Produktionsarchitekturlösung implementieren. Also, ich denke, wir müssen uns nur in der Meinung über diesen "Irrtum" unterscheiden.
Dudewad
34

Ich benutze das:

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

Hinweis: Dies funktioniert wahrscheinlich nur mit neueren Browsern, insbesondere diesen: http://caniuse.com/#feat=domcontentloaded

Dustin Davis
quelle
13
IE9 und höher tatsächlich
Pascalius
Dies funktioniert auch hervorragend in Chrome Extension-Inhaltsskripten, wenn Sie das Ereignis document_start oder document_idle verknüpft haben.
Volomike
21

Wenn Sie sich nur für Internet Explorer 9+ interessieren , würde dieser Code ausreichen, um Folgendes zu ersetzen jQuery.ready:

    document.addEventListener("DOMContentLoaded", callback);

Wenn Sie sich über Internet Explorer 6 und einige wirklich seltsame und seltene Browser Sorgen machen , funktioniert dies:

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();
        }
    }
},
Dan
quelle
18

Diese Frage wurde vor langer Zeit gestellt. Für alle, die diese Frage nur sehen, gibt es jetzt eine Site mit dem Namen "Sie benötigen möglicherweise keine JQuery", die - je nach erforderlicher IE-Unterstützung - alle Funktionen von JQuery aufschlüsselt und einige alternative, kleinere Bibliotheken bereitstellt.

IE8-Dokument bereit Skript nach Sie benötigen möglicherweise keine Abfrage

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();
        });
}
Chugadie
quelle
Ich frage mich, warum das 'onreadystatechange'eher notwendig ist alsdocument.attachEvent('onload', fn);
Luke
13

Ich habe dies kürzlich für eine mobile Website verwendet. Dies ist John Resigs vereinfachte Version von "Pro JavaScript Techniques". Es hängt von addEvent ab.

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;
})();
James
quelle
13
Seien Sie vorsichtig mit diesem Code. Es ist NICHT gleichbedeutend mit $ (Dokument) .ready. Dieser Code löst den Rückruf aus, wenn document.body bereit ist, was nicht garantiert, dass das DOM vollständig geladen ist.
Karolis
12

Browserübergreifend (auch alte Browser) und eine einfache Lösung:

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

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

Alarm in jsfiddle anzeigen

Pawel
quelle
Außer wenn das Laden des DOM mehr als 30 ms dauert, wird Ihr Code nicht ausgeführt.
Quelklef
1
@Quelklef das ist setInterval nicht setTimeout
Pawel
11

Die jQuery-Antwort war für mich ziemlich nützlich. Mit ein wenig Raffinesse passte es gut zu meinen Bedürfnissen. Ich hoffe es hilft jemand anderem.

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 )
}
Miere
quelle
In einigen Browsern muss das removeListenerDokument als Kontext aufgerufen werden, d. h. removeListener.call(document, ...
Ron
9

Hier ist das kleinste Code-Snippet zum Testen von DOM, das für alle Browser (auch IE 8) geeignet ist:

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

Siehe diese Antwort .

Antara Roy
quelle
6

Fügen Sie dies einfach am Ende Ihrer HTML-Seite hinzu ...

<script>
    Your_Function();
</script>

Weil HTML-Dokumente von oben nach unten analysiert werden.

davefrassoni
quelle
7
Woher wissen Sie, dass DOM erstellt wird, wenn dieser Code ausgeführt wird? Einschließlich geladenes und analysiertes CSS? Dafür ist die Browser-API DOMContentLoaded konzipiert.
Dan
Es kommt wirklich darauf an, was er mit js machen will. Ob er wirklich etwas ausführen muss, wenn die Seite fertig ist oder nicht.
Davefrassoni
5

Es lohnt sich, in Rock Solid addEvent () und http://www.braksator.com/how-to-make-your-own-jquery nachzuschauen .

Hier ist der Code für den Fall, dass die Site ausfällt

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");});
Ben
quelle
Die zweite Verbindung ist unterbrochen.
Peter Mortensen
4

Dieser browserübergreifende Code ruft eine Funktion auf, sobald das DOM bereit ist:

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

So funktioniert das:

  1. In der ersten Zeile wird domReadydie toStringMethode der Funktion aufgerufen, um eine Zeichenfolgendarstellung der übergebenen Funktion abzurufen und in einen Ausdruck zu verpacken, der die Funktion sofort aufruft.
  2. Der Rest von domReadyerstellt ein Skriptelement mit dem Ausdruck und hängt es an bodydas Dokument an.
  3. Der Browser führt Skript-Tags aus, an die angehängt wird, bodynachdem das DOM bereit ist.

Wenn Sie dies beispielsweise tun domReady(function(){alert();});, wird Folgendes an das bodyElement angehängt :

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

Beachten Sie, dass dies nur für benutzerdefinierte Funktionen funktioniert. Folgendes wird nicht funktionieren:domReady(alert);

Max Heiber
quelle
3

Wie wäre es mit dieser Lösung?

// 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();
};
Mike
quelle
3
Sie können addEventListener für Fenster mit "load" verwenden. Listener werden nacheinander ausgeführt und müssen nicht manuell verkettet werden.
Zaffy
1
Aber die Last ist anders als fertig. Das "Laden" erfolgt sogar, bevor das Dokument "bereit" ist. In ein fertiges Dokument ist das DOM geladen, in ein geladenes Fenster muss das DOM nicht unbedingt bereit sein. Gute Antwort
Mzn
1
@ Mzn: Ich denke das ist rückwärts. Ich denke, dass das Dokument fertig ist, bevor das Fenster geladen wird. "Im Allgemeinen muss nicht gewartet werden, bis alle Bilder vollständig geladen sind. Wenn Code früher ausgeführt werden kann, ist es normalerweise am besten, ihn in einem Handler abzulegen, der an die .ready () -Methode gesendet wird." ( api.jquery.com/load-event )
Tyler Rick
Dies überschreibt den Rest der window.onload-Ereignisse auf der Seite und würde Probleme verursachen. Es sollte ein Ereignis zusätzlich zu dem vorhandenen hinzufügen.
Teoman Shipahi
Das Ladeereignis kann zu spät auftreten. Es ist schmerzhaft, es zu verwenden, wenn es von externen JS / Images von Drittanbietern abhängt ... Ein nicht reagierender Server, den Sie nicht kontrollieren und bei dem alles ausfällt. Die Verwendung von DOMContentLoaded ist nicht nur eine Optimierung, sondern auch sicherer!
Dotpush
3

Es ist immer gut, JavaScript-Entsprechungen im Vergleich zu jQuery zu verwenden. Ein Grund ist, dass eine Bibliothek weniger abhängig ist und viel schneller als die jQuery-Entsprechungen.

Eine fantastische Referenz für jQuery-Äquivalente ist http://youmightnotneedjquery.com/ .

Was Ihre Frage betrifft, habe ich den folgenden Code aus dem obigen Link übernommen :) Die einzige Einschränkung ist, dass er nur mit Internet Explorer 9 und höher funktioniert .

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

Am minimalsten und 100% funktionsfähig

Ich habe die Antwort von PlainJS ausgewählt und sie funktioniert gut für mich. Es wird DOMContentLoadedso erweitert , dass es in allen Browsern akzeptiert werden kann.


Diese Funktion entspricht der $(document).ready()Methode von jQuery :

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

Im Gegensatz zu jQuery wird dieser Code jedoch nur in modernen Browsern (IE> 8) ordnungsgemäß ausgeführt und nicht, falls das Dokument zum Zeitpunkt des Einfügens dieses Skripts bereits gerendert ist (z. B. über Ajax). Deshalb müssen wir dies ein wenig erweitern:

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

Dies deckt grundsätzlich alle Möglichkeiten ab und ist ein praktikabler Ersatz für den jQuery-Helfer.

Shivam Sharma
quelle
2

Wir haben eine schnelle und schmutzige browserübergreifende Implementierung gefunden, die in den einfachsten Fällen mit einer minimalen Implementierung den Trick ausführen kann:

window.onReady = function onReady(fn){
    document.body ? fn() : setTimeout(function(){ onReady(fn);},50);
};
malko
quelle
was ist doc.body!?
Nabi KAZ
2

Die hier vorgestellten Lösungen setTimeout / setInterval funktionieren nur unter bestimmten Umständen.

Das Problem tritt insbesondere in älteren Internet Explorer-Versionen bis 8 auf.

Die Variablen, die den Erfolg dieser setTimeout / setInterval-Lösungen beeinflussen, sind:

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

Der ursprüngliche (native Javascript) Code zur Lösung dieses speziellen Problems ist hier:

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

Dies ist der Code, aus dem das jQuery-Team seine Implementierung erstellt hat.

Diego Perini
quelle
1

Hier ist, was ich benutze, es ist schnell und deckt alle Grundlagen ab, die ich denke; funktioniert für alles außer IE <9.

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

Dies scheint alle Fälle zu erfassen:

  • wird sofort ausgelöst, wenn das DOM bereits bereit ist (wenn das DOM nicht "geladen", sondern entweder "interaktiv" oder "vollständig" ist)
  • Wenn das DOM noch geladen wird, richtet es einen Ereignis-Listener ein, wenn das DOM verfügbar ist (interaktiv).

Das DOMContentLoaded-Ereignis ist in IE9 und allem anderen verfügbar, daher denke ich persönlich, dass es in Ordnung ist, dies zu verwenden. Schreiben Sie die Pfeilfunktionsdeklaration in eine reguläre anonyme Funktion um, wenn Sie Ihren Code nicht von ES2015 auf ES5 übertragen.

Wenn Sie warten möchten, bis alle Assets geladen, alle Bilder usw. angezeigt werden, verwenden Sie stattdessen window.onload.

Olemak
quelle
1

Wenn Sie keine sehr alten Browser unterstützen müssen, können Sie dies auch dann tun, wenn Ihr externes Skript mit einem asynchronen Attribut geladen ist :

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");
});
user4617883
quelle
0

Für IE9 +:

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

Wenn Sie jQuery am unteren Rand von BODY laden, aber Probleme mit Code haben, der jQuery (<func>) oder jQuery (document) .ready (<func>) schreibt , lesen Sie jqShim auf Github.

Anstatt eine eigene dokumentbereite Funktion neu zu erstellen, werden die Funktionen einfach beibehalten, bis jQuery verfügbar ist, und dann wie erwartet mit jQuery fortgefahren. Wenn Sie jQuery an den unteren Rand des Körpers verschieben, müssen Sie das Laden der Seite beschleunigen. Sie können dies dennoch erreichen, indem Sie die Datei jqShim.min.js in den Kopf Ihrer Vorlage einfügen.

Am Ende habe ich diesen Code geschrieben, um alle Skripte in WordPress in die Fußzeile zu verschieben, und nur dieser Shim-Code befindet sich jetzt direkt in der Kopfzeile.

Matt Pileggi
quelle
0

Versuche dies:

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!");
});

quelle
Lol du wirst den Rückruf zweimal ausführen
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 bietet einen Rückruf, wenn der HTML-Dom für den vollständigen Zugriff / Parse / Manipulation bereit ist.

onWinLoad bietet einen Rückruf, wenn alles geladen wurde (Bilder usw.)

  • Diese Funktionen können jederzeit aufgerufen werden.
  • Unterstützt mehrere "Listener".
  • Funktioniert in jedem Browser.
Jakob Sternberg
quelle
0
(function(f){
  if(document.readyState != "loading") f();
  else document.addEventListener("DOMContentLoaded", f);
})(function(){
  console.log("The Document is ready");
});
Dustin Poissant
quelle
Was fügt dies hinzu, was die anderen Antworten nicht tun?
Dwjohnston
Es verwendet einen in sich geschlossenen Verschluss (füllt den globalen "Fenster" -Bereich nicht aus), funktioniert in allen Browsern und ist sehr kompakt. Ich sehe keine anderen Antworten wie diese.
Dustin Poissant
Es funktioniert auch, nachdem das DOM bereits geladen wurde (wie es jQuery.ready tut), was die meisten dieser Antworten nicht tun.
Dustin Poissant
0

Die meisten Vanilla JS Ready-Funktionen berücksichtigen NICHT das Szenario, in dem der DOMContentLoadedHandler festgelegt wird, nachdem das Dokument bereits geladen wurde. Dies bedeutet, dass die Funktion niemals ausgeführt wird . Dies kann passieren, wenn Sie DOMContentLoadedin einem asyncexternen Skript ( <script async src="file.js"></script>) suchen .

Der folgende Code prüft DOMContentLoadednur, ob das Dokument noch readyStatenicht vorhanden ist interactiveoder nicht complete.

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

Wenn Sie auch den IE unterstützen möchten:

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!
});
Null
quelle
0

Ich benutze einfach:

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

Und anders document.addEventListener("DOMContentLoaded" //etcals in der obersten Antwort funktioniert es bereits in IE9 - http://caniuse.com/#search=DOMContentLoaded nur IE11 an.

Interessanterweise bin ich setTimeout2009 auf diese Lösung gestoßen : Ist die Überprüfung der Bereitschaft des DOM-Overkills?, was wahrscheinlich etwas besser formuliert sein könnte, da ich meinte "ist es übertrieben, die komplizierteren Ansätze verschiedener Frameworks zu verwenden, um die Bereitschaft des DOM zu überprüfen".

Meine beste Erklärung dafür, warum diese Technik funktioniert, ist, dass nach Erreichen des Skripts mit einem solchen setTimeout das DOM gerade analysiert wird, sodass die Ausführung des Codes innerhalb des setTimeout verzögert wird, bis dieser Vorgang abgeschlossen ist.

Sauerstoff
quelle