Vanille-JavaScript-Äquivalent von jQuerys $.ready() – wie man eine Funktion aufruft, wenn die Seite/das DOM dafür bereit ist [duplicate]

Lesezeit: 11 Minuten

Benutzer-Avatar
Chris

Mit jQuery kennen wir alle das Wunderbare .ready() Funktion:

$('document').ready(function(){});

Nehmen wir jedoch an, ich möchte eine Funktion ausführen, die in Standard-JavaScript ohne Bibliothek dahinter geschrieben ist, und ich möchte eine Funktion starten, sobald die Seite bereit ist, damit umzugehen. Wie geht man das richtig an?

Ich weiß, ich kann:

window.onload="myFunction()";

Oder ich kann die verwenden body Schild:

<body onload="myFunction()">

Oder ich kann sogar am Ende der Seite alles versuchen, aber das Ende body oder html Tag wie:

<script type="text/javascript">
    myFunction();
</script>

Was ist eine browserübergreifende (alt/neu) kompatible Methode zum Ausgeben einer oder mehrerer Funktionen in einer Weise wie jQuery $.ready()?

  • Siehe dies: stackoverflow.com/questions/799981/…

    – Dan A.

    28. März 2012 um 0:00 Uhr

Benutzer-Avatar
jfriend00

In Ermangelung eines Frameworks, das die gesamte browserübergreifende Kompatibilität für Sie übernimmt, ist es am einfachsten, Ihren Code am Ende des Hauptteils aufzurufen. Dies ist schneller auszuführen als eine onload -Handler, da dieser nur darauf wartet, dass das DOM bereit ist, nicht darauf, dass alle Bilder geladen werden. Und das funktioniert in jedem Browser.

<!doctype html>
<html>
<head>
</head>
<body>
Your HTML here

<script>
// self executing function here
(function() {
   // your page initialization code here
   // the DOM will be available here

})();
</script>
</body>
</html>

Für moderne Browser (alles ab IE9 und neuer und jede Version von Chrome, Firefox oder Safari), wenn Sie in der Lage sein möchten, eine jQuery wie $(document).ready() Methode, die Sie von überall aufrufen können (ohne sich Gedanken darüber zu machen, wo das aufrufende Skript positioniert ist), können Sie einfach so etwas verwenden:

function docReady(fn) {
    // see if DOM is already available
    if (document.readyState === "complete" || document.readyState === "interactive") {
        // call on next available tick
        setTimeout(fn, 1);
    } else {
        document.addEventListener("DOMContentLoaded", fn);
    }
}    

Verwendungszweck:

docReady(function() {
    // DOM is loaded and ready for manipulation here
});

Wenn Sie volle Cross-Browser-Kompatibilität (einschließlich alter Versionen von IE) benötigen und nicht warten möchten window.onloaddann sollten Sie sich wahrscheinlich ansehen, wie ein Framework wie jQuery dies implementiert $(document).ready() Methode. Es ist ziemlich kompliziert, abhängig von den Fähigkeiten des Browsers.

Um Ihnen eine kleine Vorstellung davon zu geben, was jQuery tut (was überall dort funktioniert, wo das script-Tag platziert wird).

Wenn unterstützt, versucht es den Standard:

document.addEventListener('DOMContentLoaded', fn, false);

mit Rückgriff auf:

window.addEventListener('load', fn, false )

oder für ältere Versionen von IE verwendet es:

document.attachEvent("onreadystatechange", fn);

mit Rückgriff auf:

window.attachEvent("onload", fn);

Und es gibt einige Problemumgehungen im IE-Codepfad, denen ich nicht ganz folge, aber es sieht so aus, als hätte es etwas mit Frames zu tun.


Hier ist ein vollständiger Ersatz für jQuery .ready() in reinem Javascript geschrieben:

(function(funcName, baseObj) {
    // The public function name defaults to window.docReady
    // but you can pass in your own object and own function name and those will be used
    // if you want to put them in a different namespace
    funcName = funcName || "docReady";
    baseObj = baseObj || window;
    var readyList = [];
    var readyFired = false;
    var readyEventHandlersInstalled = false;

    // call this when the document is ready
    // this function protects itself against being called more than once
    function ready() {
        if (!readyFired) {
            // this must be set to true before we start calling callbacks
            readyFired = true;
            for (var i = 0; i < readyList.length; i++) {
                // if a callback here happens to add new ready handlers,
                // the docReady() function will see that it already fired
                // and will schedule the callback to run right after
                // this event loop finishes so all handlers will still execute
                // in order and no new ones will be added to the readyList
                // while we are processing the list
                readyList[i].fn.call(window, readyList[i].ctx);
            }
            // allow any closures held by these functions to free
            readyList = [];
        }
    }

    function readyStateChange() {
        if ( document.readyState === "complete" ) {
            ready();
        }
    }

    // This is the one public interface
    // docReady(fn, context);
    // the context argument is optional - if present, it will be passed
    // as an argument to the callback
    baseObj[funcName] = function(callback, context) {
        if (typeof callback !== "function") {
            throw new TypeError("callback for docReady(fn) must be a function");
        }
        // if ready has already fired, then just schedule the callback
        // to fire asynchronously, but right away
        if (readyFired) {
            setTimeout(function() {callback(context);}, 1);
            return;
        } else {
            // add the function and context to the list
            readyList.push({fn: callback, ctx: context});
        }
        // if document already ready to go, schedule the ready function to run
        if (document.readyState === "complete") {
            setTimeout(ready, 1);
        } else if (!readyEventHandlersInstalled) {
            // otherwise if we don't have event handlers installed, install them
            if (document.addEventListener) {
                // first choice is DOMContentLoaded event
                document.addEventListener("DOMContentLoaded", ready, false);
                // backup is window load event
                window.addEventListener("load", ready, false);
            } else {
                // must be IE
                document.attachEvent("onreadystatechange", readyStateChange);
                window.attachEvent("onload", ready);
            }
            readyEventHandlersInstalled = true;
        }
    }
})("docReady", window);

Die neueste Version des Codes wird öffentlich auf GitHub unter geteilt https://github.com/jfriend00/docReady

Verwendungszweck:

// pass a function reference
docReady(fn);

// use an anonymous function
docReady(function() {
    // code here
});

// pass a function reference and a context
// the context will be passed to the function as the first argument
docReady(fn, context);

// use an anonymous function with a context
docReady(function(context) {
    // code here that can use the context argument that was passed to docReady
}, ctx);

Dies wurde getestet in:

IE6 and up
Firefox 3.6 and up
Chrome 14 and up
Safari 5.1 and up
Opera 11.6 and up
Multiple iOS devices
Multiple Android devices

Arbeitsimplementierung und Prüfstand: http://jsfiddle.net/jfriend00/YfD3C/


Hier ist eine Zusammenfassung, wie es funktioniert:

  1. Erstelle ein IIFE (unmittelbar aufgerufener Funktionsausdruck), damit wir nicht-öffentliche Zustandsvariablen haben können.
  2. Deklarieren Sie eine öffentliche Funktion docReady(fn, context)
  3. Wann docReady(fn, context) aufgerufen wird, prüfen Sie, ob der Ready-Handler bereits gefeuert hat. Wenn dies der Fall ist, planen Sie einfach, dass der neu hinzugefügte Rückruf direkt nach dem Ende dieses JS-Threads ausgelöst wird setTimeout(fn, 1).
  4. Wenn der Ready-Handler noch nicht ausgelöst wurde, fügen Sie diesen neuen Callback der Liste der später aufzurufenden Callbacks hinzu.
  5. Überprüfen Sie, ob das Dokument bereits fertig ist. Wenn dies der Fall ist, führen Sie alle bereiten Handler aus.
  6. Wenn wir noch keine Ereignis-Listener installiert haben, um zu wissen, wann das Dokument fertig ist, dann installieren Sie sie jetzt.
  7. Wenn document.addEventListener vorhanden ist, installieren Sie dann Event-Handler mit .addEventListener() für beide "DOMContentLoaded" und "load" Veranstaltungen. Das “Laden” ist ein Backup-Ereignis aus Sicherheitsgründen und sollte nicht benötigt werden.
  8. Wenn document.addEventListener existiert nicht, dann installieren Sie Event-Handler mit .attachEvent() zum "onreadystatechange" und "onload" Veranstaltungen.
  9. In dem onreadystatechange Ereignis, überprüfen Sie, ob die document.readyState === "complete" und wenn ja, rufen Sie eine Funktion auf, um alle bereiten Handler auszulösen.
  10. Rufen Sie in allen anderen Event-Handlern eine Funktion auf, um alle ready-Handler auszulösen.
  11. Überprüfen Sie in der Funktion zum Aufrufen aller bereiten Handler eine Zustandsvariable, um festzustellen, ob wir bereits ausgelöst haben. Wenn ja, tun Sie nichts. Wenn wir noch nicht aufgerufen wurden, durchlaufen Sie das Array der bereiten Funktionen und rufen Sie jede in der Reihenfolge auf, in der sie hinzugefügt wurde. Setzen Sie ein Flag, um anzuzeigen, dass diese alle aufgerufen wurden, damit sie nie mehr als einmal ausgeführt werden.
  12. Löschen Sie das Funktionsarray, damit alle Closures, die sie möglicherweise verwenden, freigegeben werden können.

Handler registriert bei docReady() werden garantiert in der Reihenfolge gefeuert, in der sie registriert wurden.

Wenn Sie anrufen docReady(fn) Nachdem das Dokument bereits fertig ist, wird der Rückruf so geplant, dass er ausgeführt wird, sobald der aktuelle Ausführungs-Thread die Verwendung abschließt setTimeout(fn, 1). Dadurch kann der aufrufende Code immer davon ausgehen, dass es sich um asynchrone Rückrufe handelt, die später aufgerufen werden, selbst wenn später der aktuelle Thread von JS beendet ist und die Aufrufreihenfolge beibehalten wird.

  • Warum wird setTimeout(fn, 1) anders als setTimeout(fn, 0) verwendet?

    – David Lange

    9. Februar um 2:11 Uhr

  • @David – Es spielt keine Rolle, da der Browser ohnehin eine minimale Timeout-Zeit von ~ 4 ms hat. Die allgemeine Idee ist, dass wir dem Leser des Codes mitteilen möchten, dass dies der Fall ist setTimeout() wird bei einem zukünftigen Tick der Ereignisschleife ausgelöst, nicht sofort. Während sogar setTimeout(fn, 0) bei einem zukünftigen Tick der Ereignisschleife ausgelöst wird, dachte ich, es wäre für einen weniger gebildeten Leser des Codes klarer, wenn ich einen Wert ungleich Null für die Zeit verwenden würde, um zu veranschaulichen, dass dies in der Zukunft geschehen wird, nicht sofort. So oder so keine große Sache.

    – jfriend00

    9. Februar um 2:41 Uhr

  • Danke dafür! Ich arbeite derzeit an einer Layoutbibliothek für das Web mit Constraint-Layouts (Android-Stil) und musste die Ladezeit optimieren und das anfängliche ungeordnete Flimmern aufgrund des Standard-DOM-Status entfernen, bevor das js einsetzt und Ihre Antwort wirklich geholfen hat.

    – gbenroscience

    4. August um 0:49 Uhr

Benutzer-Avatar
Tom Stickel

Wenn Sie tun VANILLE schmucklos JavaScript ohne jQuery, dann müssen Sie verwenden (Internet Explorer 9 oder höher):

document.addEventListener("DOMContentLoaded", function(event) {
    // Your code to run since DOM is loaded and ready
});

Oben ist das Äquivalent von jQuery .ready:

$(document).ready(function() {
    console.log("Ready!");
});

Was AUCH so geschrieben werden könnte, dass jQuery ausgeführt wird, nachdem das Ready-Ereignis auftritt.

$(function() {
    console.log("ready!");
});

NICHT MIT UNTEN VERWECHSELN (was nicht DOM-fähig sein soll):

Verwenden Sie KEINE IIFE so, dass es sich selbst ausführt:

 Example:

(function() {
   // Your page initialization code here  - WRONG
   // The DOM will be available here   - WRONG
})();

Dieses IIFE wartet NICHT darauf, dass Ihr DOM geladen wird. (Ich spreche sogar von der neuesten Version des Chrome-Browsers!)

  • play() ist fehlgeschlagen, weil der Benutzer nicht zuerst mit dem Dokument interagiert hat

    – CS QGB

    24. November 2021 um 10:16 Uhr

  • Ja, das erste für mich: D Wenn Sie dem Sharepoint-Skripteditor ein reines Skript hinzufügen möchten, verwenden Sie dies .. document.addEventListener (“DOMContentLoaded”, function (event)

    – missCEREN

    16. Februar um 22:14 Uhr

Benutzer-Avatar
Ram Patra

Einige der möglichen Wege möchte ich hier zusammen mit a nennen reiner Javascript-Trick, der in allen Browsern funktioniert:

// with jQuery 
$(document).ready(function(){ /* ... */ });

// shorter jQuery version 
$(function(){ /* ... */ });

// without jQuery (doesn't work in older IEs)
document.addEventListener('DOMContentLoaded', function(){ 
    // your code goes here
}, false);

// and here's the trick (works everywhere)
function r(f){/in/.test(document.readyState)?setTimeout('r('+f+')',9):f()}
// use like
r(function(){
    alert('DOM Ready!');
});

Der Trick hier, wie durch die erklärt ursprünglicher Autorist, dass wir die überprüfen document.readyState Eigentum. Wenn es die Zeichenfolge enthält in (wie in uninitialized und loadingdie ersten zwei DOM-bereite Zustände von 5) setzen wir ein Timeout und prüfen es erneut. Andernfalls führen wir die übergebene Funktion aus.

Und hier ist die jsFiddle für den Trick, der funktioniert in allen Browsern.

Dank an Tutorialzine für die Aufnahme in ihr Buch.

  • Sehr schlechter Ansatz, Verwendung einer Timeout-Schleife mit einem beliebigen Intervall von 9 ms und Verwendung von eval. Es macht auch nicht viel Sinn, nur nach /in/ zu suchen.

    – Vitim.us

    22. November 2015 um 14:51 Uhr

Getestet in IE9 und den neuesten Firefox und Chrome und auch in IE8 unterstützt.

document.onreadystatechange = function () {
  var state = document.readyState;
  if (state == 'interactive') {
      init();
  } else if (state == 'complete') {
      initOnCompleteLoad();
  }
}​;

Beispiel: http://jsfiddle.net/electricvisions/Jacck/

UPDATE – wiederverwendbare Version

Ich habe gerade folgendes entwickelt. Es ist ein ziemlich einfaches Äquivalent zu jQuery oder Dom ready ohne Abwärtskompatibilität. Es muss wahrscheinlich noch weiter verfeinert werden. Getestet in den neuesten Versionen von Chrome, Firefox und IE (10/11) und sollte wie kommentiert in älteren Browsern funktionieren. Ich werde aktualisieren, wenn ich irgendwelche Probleme finde.

window.readyHandlers = [];
window.ready = function ready(handler) {
  window.readyHandlers.push(handler);
  handleState();
};

window.handleState = function handleState () {
  if (['interactive', 'complete'].indexOf(document.readyState) > -1) {
    while(window.readyHandlers.length > 0) {
      (window.readyHandlers.shift())();
    }
  }
};

document.onreadystatechange = window.handleState;

Verwendungszweck:

ready(function () {
  // your code here
});

Es wurde geschrieben, um das asynchrone Laden von JS zu handhaben, aber Sie möchten dieses Skript möglicherweise zuerst synchronisieren, es sei denn, Sie minimieren. Ich fand es nützlich in der Entwicklung.

Moderne Browser unterstützen auch das asynchrone Laden von Skripten, was das Erlebnis weiter verbessert. Unterstützung für Async bedeutet, dass mehrere Skripte gleichzeitig heruntergeladen werden können, während die Seite weiterhin gerendert wird. Passen Sie einfach auf, wenn Sie von anderen Skripten abhängig sind, die asynchron geladen werden, oder verwenden Sie einen Minifier oder etwas wie Browserify, um Abhängigkeiten zu behandeln.

Benutzer-Avatar
Lorcan O’Neill

Die guten Leute bei HubSpot haben eine Ressource, wo Sie reine Javascript-Methoden finden können, um viel jQuery-Güte zu erreichen – einschließlich ready

http://youmightnotneedjquery.com/#ready

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

Beispiel Inline-Nutzung:

ready(function() { alert('hello'); });

Benutzer-Avatar
Peter Mortensen

Ich bin mir nicht ganz sicher, was du fragst, aber vielleicht hilft das hier:

window.onload = function(){
    // Code. . .

}

Oder:

window.onload = main;

function main(){
    // Code. . .

}

Benutzer-Avatar
rogerpack

Ihre Methode (Skript vor dem schließenden Body-Tag platzieren)

<script>
   myFunction()
</script>
</body>
</html>

ist eine zuverlässige Möglichkeit, alte und neue Browser zu unterstützen.

1315900cookie-checkVanille-JavaScript-Äquivalent von jQuerys $.ready() – wie man eine Funktion aufruft, wenn die Seite/das DOM dafür bereit ist [duplicate]

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy