Was ist das Nicht-jQuery-Äquivalent von '$ (document) .ready ()'?

444

Was ist das Nicht-jQuery-Äquivalent von $(document).ready() ?

TIMEX
quelle
4
Wenn Sie das $(document).ready()Ereignis von jQuery ohne Verwendung einer Bibliothek reproduzieren möchten, sehen Sie sich dies an: stackoverflow.com/questions/1795089/…
CMS
@OP: Auf Seite 89 von Pro JavaScript Techniques finden Sie eine Vanille-JavaScript-Implementierung von $(document).ready()- books.google.com/… . Es verwendet auch die addEventereignisbindende Abstraktion von Dean Edwards, deren Code ebenfalls im Buch enthalten ist :)
Russ Cam
2
mögliches Duplikat von $ (Dokument). bereits gleichwertig ohne jQuery
Qantas 94 Heavy

Antworten:

75

Das Schöne daran $(document).ready()ist, dass es vorher feuert window.onload. Die Ladefunktion wartet, bis alles geladen ist, einschließlich externer Assets und Bilder. $(document).readyWird jedoch ausgelöst, wenn der DOM-Baum vollständig ist und bearbeitet werden kann. Wenn Sie DOM ohne jQuery erreichen möchten, können Sie in diese Bibliothek einchecken. Jemand hat nur den readyTeil aus jQuery extrahiert . Es ist schön klein und vielleicht nützlich:

bereits bei Google Code

Doug Neiner
quelle
4
DomReady-Code-Netzwerk! via @CMS auf github: github.com/cms/domready/network
Kzqai
44
Dies beantwortet weder die Frage noch zeigt es einen Nicht-jQuery-Code an. Wie kam es zu so vielen positiven Stimmen?
Daniel W.
3
@ DanielW. Weil es einfach und praktisch ist. Die meisten von uns kamen hierher, um sicherzustellen, dass DOM für die Verwendung durch Javascript-Code bereit ist.
Abarazal
Ja, aber einige von uns kamen hierher, um eine tatsächliche Antwort zu erhalten.
Slbox
611

Dies funktioniert perfekt von ECMA

document.addEventListener("DOMContentLoaded", function() {
  // code...
});

Das window.onloadist gleich nicht zu JQuery $(document).readyweil $(document).readywartet nur auf den Baum DOM während window.onloadalle Elemente überprüfen , einschließlich externer Vermögenswerte und Bilder.

EDIT : IE8 und älteres Äquivalent hinzugefügt, dank Jan Derks Beobachtung. Sie können die Quelle dieses Codes auf MDN unter diesem Link lesen :

// alternative to DOMContentLoaded
document.onreadystatechange = function () {
    if (document.readyState == "interactive") {
        // Initialize your application or run some code.
    }
}

Neben gibt es noch andere Möglichkeiten "interactive". Weitere Informationen finden Sie unter dem MDN- Link.

sospedra
quelle
Mit Benjamin einverstanden sein. Sie können attachEvent nicht einfach verwenden. Beispiel: In Chrome erhalten Sie: Uncaught TypeError: document.attachEvent ist keine Funktion. Verwenden Sie die verknüpfte Antwort von Jan Derk.
Manuel Arwed Schmidt
9
Was ist, wenn das Dokument bereits geladen wurde, als dieses Skript aufgerufen wurde? Nichts wird überhaupt passieren :(
Oriadam
8
@ Deerloper Nein, habe es gerade auf der Chrome-Konsole versucht - nichts ist passiert: document.addEventListener("DOMContentLoaded",function(){console.log(123)})versuche es jetzt
Oriadam
2
Unterstützung von DOMContentLoaded in Browsern: caniuse.com/domcontentloaded
Guillaume Husta
1
@elliottregan das stimmt, ich entferne den Kommentar, um diesen Thread nicht zu verschmutzen. Ich schlage vor, dass Sie alle das Gleiche tun :) Und lassen Sie einen Kommentar, falls erforderlich, auf den Kommentar hinweisen, falls erforderlich. Da das ein Extra ist, weil es über die OC-Fragen hinausgeht
sospedra
43

Eine kleine Sache, die ich zusammengestellt habe

domready.js

(function(exports, d) {
  function domReady(fn, context) {

    function onReady(event) {
      d.removeEventListener("DOMContentLoaded", onReady);
      fn.call(context || exports, event);
    }

    function onReadyIe(event) {
      if (d.readyState === "complete") {
        d.detachEvent("onreadystatechange", onReadyIe);
        fn.call(context || exports, event);
      }
    }

    d.addEventListener && d.addEventListener("DOMContentLoaded", onReady) ||
    d.attachEvent      && d.attachEvent("onreadystatechange", onReadyIe);
  }

  exports.domReady = domReady;
})(window, document);

Wie man es benutzt

<script src="domready.js"></script>
<script>
  domReady(function(event) {
    alert("dom is ready!");
  });
</script>

Sie können den Kontext, in dem der Rückruf ausgeführt wird, auch ändern, indem Sie ein zweites Argument übergeben

function init(event) {
  alert("check the console");
  this.log(event);
}

domReady(init, console);
Vielen Dank
quelle
2
Vielen Dank. Ich mag die Tatsache, dass es abwärtskompatibel ist. Sich vorwärts zu bewegen bedeutet nicht, weniger glückliche Menschen zurückzulassen. Es ist unglücklich, keinen modernen Browser verwenden zu können (aus welchem ​​Grund auch immer) ...
CO
28

Jetzt, da es 2018 ist, ist hier eine schnelle und einfache Methode.

Dadurch wird ein Ereignis-Listener hinzugefügt. Wenn er jedoch bereits ausgelöst wurde, überprüfen wir, ob der Dom bereit oder vollständig ist. Dies kann ausgelöst werden, bevor oder nachdem Unterressourcen vollständig geladen wurden (Bilder, Stylesheets, Frames usw.).

function domReady(fn) {
  // If we're early to the party
  document.addEventListener("DOMContentLoaded", fn);
  // If late; I mean on time.
  if (document.readyState === "interactive" || document.readyState === "complete" ) {
    fn();
  }
}

domReady(() => console.log("DOM is ready, come and get it!"));

Zusätzliche Lesungen


Aktualisieren

Hier sind einige schnelle Hilfsprogramme, die den von mir geschriebenen Standard-ES6-Import und -Export verwenden und auch TypeScript enthalten. Vielleicht kann ich diese zu einer schnellen Bibliothek machen, die als Abhängigkeit in Projekte installiert werden kann.

JavaScript

export const domReady = (callBack) => {
  if (document.readyState === "loading") {
    document.addEventListener('DOMContentLoaded', callBack);
  }
  else {
    callBack();
  }
}

export const windowReady = (callBack) => {
  if (document.readyState === 'complete') {
    callBack();
  }
  else {
    window.addEventListener('load', callBack);
  }
}

Typoskript

export const domReady = (callBack: () => void) => {
  if (document.readyState === "loading") {
    document.addEventListener('DOMContentLoaded', callBack);
  }
  else {
    callBack();
  }
}

export const windowReady = (callBack: () => void) => {
  if (document.readyState === 'complete') {
    callBack();
  }
  else {
    window.addEventListener('load', callBack);
  }
}

Versprechen

export const domReady = new Promise(resolve => {
  if (document.readyState === "loading") {
    document.addEventListener('DOMContentLoaded', resolve);
  }
  else {
    resolve();
  }
});

export const windowReady = new Promise(resolve => {
  if (document.readyState === 'complete') {
    resolve();
  }
  else {
    window.addEventListener('load', resolve);
  }
});
CTS_AE
quelle
16

Laut http://youmightnotneedjquery.com/#ready ist bereits ein netter Ersatz, der noch mit IE8 funktioniert

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

// test
window.ready(function() {
    alert('it works');
});

Verbesserungen : Persönlich würde ich auch prüfen, ob der Typ fneine Funktion ist. Und wie @elliottregan vorgeschlagen hat, entfernen Sie den Ereignis-Listener nach der Verwendung.

Der Grund, warum ich diese Frage zu spät beantworte, ist, dass ich nach dieser Antwort gesucht habe, sie aber hier nicht finden konnte. Und ich denke, das ist die beste Lösung.

online Thomas
quelle
1
Ja, das ist meiner Meinung nach die beste Antwort. Einfach zu lesen und führt den Code aus, auch wenn das DOM bereits geladen ist. Das einzige, was ich hinzufügen möchte, ist, den Ereignislistener zu entfernen, nachdem das Ereignis ausgelöst wurde.
Elliottottregan
14

Es gibt einen standardbasierten Ersatz, DOMContentLoaded, der von über 90% der Browser unterstützt wird, jedoch nicht von IE8 (siehe unten: Code, der von JQuery für die Browserunterstützung verwendet wird) :

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 );
}
Zigri2612
quelle
1
Neue jQuery fiel für ältere Browser - Unterstützung und jetzt nur sie haben DOMContentLoadedund loadEreignisse mit addEventListener, und zuerst das Feuer beiden Hörer entfernen, so dass es zweimal nicht ausgelöst.
Jcubic
8

In einfachem Vanille-JavaScript ohne Bibliotheken? Es ist ein Fehler. $ist einfach ein Bezeichner und undefiniert, sofern Sie ihn nicht definieren.

jQuery definiert $als sein eigenes "Alles-Objekt" (auch bekannt als " jQuerySie können es verwenden, ohne mit anderen Bibliotheken in Konflikt zu geraten)". Wenn Sie jQuery (oder eine andere Bibliothek, die es definiert) nicht verwenden, $wird es nicht definiert.

Oder fragen Sie, was das Äquivalent in einfachem JavaScript ist? In diesem Fall möchten Sie wahrscheinlich window.onload, was nicht genau gleichwertig ist, aber der schnellste und einfachste Weg ist, um dem gleichen Effekt in Vanille-JavaScript nahe zu kommen.

Brian Campbell
quelle
39
Für die vielen Downvoter dieser Antwort (und die anderen unten): Als diese Frage gestellt wurde, hieß es einfach: "Was ist $ (document) .ready () in Javascript? Nicht jquery. Was ist das?" Es klang, als würde er fragen, was das in einfachem Vanille-JavaScript ohne geladene jQuery bedeutet. In meiner Antwort habe ich versucht, diese Frage zu beantworten und die einfachste Antwort für einfaches Vanille-JavaScript ohne jQuery oder andere Bibliotheken zu geben, falls er dies meinte. Beachten Sie, dass der gesamte zusätzliche Kontext von anderen Personen hinzugefügt wurde, die erraten, was die Frage stellte, nicht vom Originalposter.
Brian Campbell
5

Der einfachste Weg in neueren Browsern wäre die Verwendung der entsprechenden GlobalEventHandler , onDOMContentLoaded , onload , onloadeddata (...)

onDOMContentLoaded = (function(){ console.log("DOM ready!") })()

onload = (function(){ console.log("Page fully loaded!") })()

onloadeddata = (function(){ console.log("Data loaded!") })()

Das DOMContentLoaded-Ereignis wird ausgelöst, wenn das ursprüngliche HTML-Dokument vollständig geladen und analysiert wurde, ohne darauf zu warten, dass Stylesheets, Bilder und Subframes vollständig geladen werden. Eine ganz andere Ereignislast sollte nur verwendet werden, um eine vollständig geladene Seite zu erkennen. Es ist ein unglaublich beliebter Fehler, load zu verwenden, wenn DOMContentLoaded viel angemessener wäre. Seien Sie also vorsichtig.

https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded

Die verwendete Funktion ist eine IIFE, die in diesem Fall sehr nützlich ist, da sie sich selbst auslöst, wenn sie bereit ist:

https://en.wikipedia.org/wiki/Immedially-invoked_function_expression

Es ist offensichtlich angemessener, es am Ende eines Skripts zu platzieren.

In ES6 können wir es auch als Pfeilfunktion schreiben:

onload = (() => { console.log("ES6 page fully loaded!") })()

Am besten verwenden Sie die DOM-Elemente. Wir können warten, bis eine Variable bereit ist, die ein IIFE mit Pfeil auslöst.

Das Verhalten ist das gleiche, jedoch mit geringerer Auswirkung auf den Speicher.

footer = (() => { console.log("Footer loaded!") })()
<div id="footer">

In vielen Fällen wird das Dokumentobjekt auch ausgelöst, wenn es bereit ist , zumindest in meinem Browser. Die Syntax ist dann sehr schön, aber es müssen weitere Tests zur Kompatibilität durchgeführt werden.

document=(()=>{    /*Ready*/   })()
NVRM
quelle
Könnte ein IIFE-Trigger, bevor das DOM fertig ist, Elemente danach laden?
CTS_AE
Sicher, es ist nur eine Funktion, eine anonyme Funktion in einem Abschluss.
NVRM
0

Der Body onLoad könnte auch eine Alternative sein:

<html>
<head><title>Body onLoad Exmaple</title>

<script type="text/javascript">
    function window_onload() {
        //do something
    }
</script>

</head>
<body onLoad="window_onload()">

</body>
</html>
joan16v
quelle