Frage Reine JavaScript-Entsprechung von jQuerys $ .ready () - wie man eine Funktion aufruft, wenn die Seite / das DOM bereit dafür ist [duplizieren]


Diese Frage hat hier bereits eine Antwort:

Okay, das könnte nur eine dumme Frage sein, obwohl ich sicher bin, dass es viele andere Leute gibt, die von Zeit zu Zeit dieselbe Frage stellen. Ich möchte mich nur hundertprozentig sicher sein. Mit jQuery kennen wir alle das Wunderbare

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

Nehmen wir an, ich möchte eine Funktion ausführen, die in Standard-JavaScript geschrieben ist, ohne dass eine Bibliothek diese unterstützt, und dass ich eine Funktion starten möchte, sobald die Seite bereit ist, damit umzugehen. Was ist der richtige Weg, um dies zu erreichen?

Ich weiß, ich kann:

window.onload="myFunction()";

... oder ich kann das benutzen body Etikett:

<body onload="myFunction()">

... oder ich kann es am Ende der Seite nach allem versuchen, aber am Ende body oder html Stichwort wie:

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

Was ist eine browserübergreifende (alt / neu) -konforme Methode zum Ausgeben einer oder mehrerer Funktionen in einer Art wie jQuery's? $.ready()?


907
2018-03-27 23:57


Ursprung


Antworten:


Die einfachste Sache zu tun in Ermangelung eines Rahmens, der all die Cross-Browser-Kompatibilität für Sie tut, ist nur einen Aufruf an Ihren Code am Ende des Körpers. Dies ist schneller auszuführen als ein onload Handler, weil dies nur darauf wartet, dass das DOM bereit ist, nicht für alle Bilder, die geladen werden sollen. Und das funktioniert in jedem Browser.

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

Wenn Sie es wirklich nicht so machen wollen, brauchen Sie Cross-Browser-Kompatibilität, auf die Sie nicht warten wollen window.onload, dann solltest du wahrscheinlich schauen, wie ein Framework wie jQuery es implementiert $(document).ready() Methode. Es hängt ziemlich davon ab, abhängig von den Fähigkeiten des Browsers.

Um Ihnen eine kleine Vorstellung davon zu geben, was jQuery macht (was immer funktioniert, wenn das Skript-Tag platziert wird).

Wenn es unterstützt wird, versucht es den Standard:

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

mit einem Fallback zu:

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

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

document.attachEvent("onreadystatechange", fn);

mit einem Fallback zu:

window.attachEvent("onload", fn);

Und es gibt einige Workarounds im IE-Codepfad, denen ich nicht ganz folge, aber es sieht so aus, als ob es etwas mit Frames zu tun hat.


Hier ist ein vollständiger Ersatz für jQuery's .ready() in einfachem 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 veröffentlicht https://github.com/jfriend00/docReady

Verwendung:

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

Arbeitsumsetzung und Testbett: http://jsfiddle.net/jfriend00/YfD3C/


Hier ist eine Zusammenfassung, wie es funktioniert:

  1. Erstelle ein IIFE (sofort aufgerufener Funktionsausdruck), so dass wir nicht-öffentliche Statusvariablen haben können.
  2. Deklariere eine öffentliche Funktion docReady(fn, context)
  3. Wann docReady(fn, context) aufgerufen wird, überprüfen Sie, ob der Bereitschaftshandler bereits ausgelöst hat. Wenn dies der Fall ist, planen Sie einfach den neu hinzugefügten Rückruf, der ausgelöst werden soll, nachdem dieser Thread von JS beendet ist setTimeout(fn, 1).
  4. Wenn der Bereit-Handler noch nicht ausgelöst wurde, fügen Sie diesen neuen Callback der Liste der Callbacks hinzu, die später aufgerufen werden sollen.
  5. Überprüfen Sie, ob das Dokument bereits bereit ist. Wenn ja, führen Sie alle Ready-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. Ob document.addEventListener existiert, dann installieren Sie Ereignishandler mit .addEventListener() für beide "DOMContentLoaded" und "load" Veranstaltungen. Die "Last" ist ein Backup-Ereignis für die Sicherheit und sollte nicht benötigt werden.
  8. Ob 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 dies der Fall ist, rufen Sie eine Funktion auf, um alle bereiten Handler abzufeuern.
  10. Rufen Sie in allen anderen Ereignishandlern eine Funktion auf, um alle Bereit-Handler auszulösen.
  11. In der Funktion, alle Ready-Handler aufzurufen, überprüfen Sie eine Statusvariable, um zu sehen, ob wir bereits gefeuert haben. Wenn wir haben, nichts tun. Wenn wir noch nicht aufgerufen wurden, durchlaufen Sie das Array der Ready-Funktionen und rufen Sie jedes in der Reihenfolge auf, in der es hinzugefügt wurde. Setzen Sie ein Flag, um anzuzeigen, dass alle aufgerufen wurden, so dass sie nie mehr als einmal ausgeführt werden.
  12. Löschen Sie das Funktions-Array, damit alle Schließungen, die sie möglicherweise verwenden, freigegeben werden können.

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

Wenn du anrufst docReady(fn) Nachdem das Dokument bereits bereit ist, wird der Rückruf ausgeführt, sobald der aktuelle Ausführungsthread abgeschlossen ist setTimeout(fn, 1). Dadurch kann der aufrufende Code immer annehmen, dass es sich um asynchrone Callbacks handelt, die später aufgerufen werden, auch wenn später der aktuelle Thread von JS beendet wird und die aufrufende Reihenfolge beibehalten wird.


1350
2018-03-28 00:46



Ich möchte einige der möglichen Wege hier zusammen mit einem erwähnen 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 von der ursprünglicher Autorist, dass wir das überprüfen document.readyState Eigentum. Wenn es die Zeichenfolge enthält in (wie in uninitialized und loading, die ersten zwei DOM-Bereit-Status von 5) setzen wir eine Zeitüberschreitung und überprüfen erneut. Ansonsten führen wir die übergebene Funktion aus.

Und hier ist der jsFiddle für den Trick, der funktioniert über alle Browser hinweg. 

Dank an Tutorialzine um dies in ihr Buch aufzunehmen.


99
2018-05-19 07:58



Wenn du es tust VANILLE einfach JavaScript Ohne jQuery müssen Sie (Internet Explorer 9 oder höher) verwenden:

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 ALSO auch SHORTHAND geschrieben werden könnte, das jQuery wird nach dem Ready sogar laufen tritt ein.

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

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

Verwenden Sie NICHT ein IIFE wie das, das sich selbst ausführt:

 Example:

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

Dieser IIFE wartet NICHT auf das Laden Ihres DOM. (Ich spreche sogar über die neueste Version des Chrome-Browsers!)


81
2017-07-01 20:31



Getestet in IE9 und 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 relativ einfaches Gegenstück zu jQuery oder Dom, ohne Rückwärtskompatibilität. Es muss wahrscheinlich weiter verfeinert werden. Getestet in den neuesten Versionen von Chrome, Firefox und IE (10/11) und sollte in älteren Browsern funktionieren, wie sie kommentiert wurden. Ich werde aktualisieren, wenn ich 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;

Verwendung:

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

Es wurde geschrieben, um asynchres Laden von JS zu behandeln, aber Sie möchten dieses Skript möglicherweise zuerst laden, es sei denn, Sie reduzieren es. Ich habe es in der Entwicklung nützlich gefunden.

Moderne Browser unterstützen auch das asynchrone Laden von Skripten, was die Erfahrung weiter verbessert. Die Unterstützung für async bedeutet, dass mehrere Skripts gleichzeitig heruntergeladen werden können, während die Seite noch gerendert wird. Achten Sie darauf, 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.


71
2018-06-10 13:27



Die guten Leute bei HubSpot haben eine Ressource, wo Sie pure Javascript-Methoden finden können, um eine Menge 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'); });

17
2018-03-28 00:46



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.


7
2017-11-24 05:15



Bereit

function ready(fn){var d=document;(d.readyState=='loading')?d.addEventListener('DOMContentLoaded',fn):fn();}

Verwenden Sie wie

ready(function(){
    //some code
});

Für selbstaufrufenden Code

(function(fn){var d=document;(d.readyState=='loading')?d.addEventListener('DOMContentLoaded',fn):fn();})(function(){

    //Some Code here
    //DOM is avaliable
    //var h1s = document.querySelector("h1");

});

Unterstützung: IE9 +


4
2018-06-19 06:03