Vanille-JavaScript-Äquivalent von jQuerys $.ready() – wie man eine Funktion aufruft, wenn die Seite/das DOM dafür bereit ist [duplicate]
Lesezeit: 11 Minuten
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:
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
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).
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);
// 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
Hier ist eine Zusammenfassung, wie es funktioniert:
Erstelle ein IIFE (unmittelbar aufgerufener Funktionsausdruck), damit wir nicht-öffentliche Zustandsvariablen haben können.
Deklarieren Sie eine öffentliche Funktion docReady(fn, context)
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).
Wenn der Ready-Handler noch nicht ausgelöst wurde, fügen Sie diesen neuen Callback der Liste der später aufzurufenden Callbacks hinzu.
Überprüfen Sie, ob das Dokument bereits fertig ist. Wenn dies der Fall ist, führen Sie alle bereiten Handler aus.
Wenn wir noch keine Ereignis-Listener installiert haben, um zu wissen, wann das Dokument fertig ist, dann installieren Sie sie jetzt.
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.
Wenn document.addEventListener existiert nicht, dann installieren Sie Event-Handler mit .attachEvent() zum "onreadystatechange" und "onload" Veranstaltungen.
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.
Rufen Sie in allen anderen Event-Handlern eine Funktion auf, um alle ready-Handler auszulösen.
Ü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.
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
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
});
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
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();
}
};
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.
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.
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
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'); });
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. . .
}
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.
13159000cookie-checkVanille-JavaScript-Äquivalent von jQuerys $.ready() – wie man eine Funktion aufruft, wenn die Seite/das DOM dafür bereit ist [duplicate]yes
Siehe dies: stackoverflow.com/questions/799981/…
– Dan A.
28. März 2012 um 0:00 Uhr