it-swarm.com.de

Reines JavaScript-Äquivalent zu jQueries $ .ready () - wie man eine Funktion aufruft, wenn die Seite / das DOM dafür bereit ist

Okay, das könnte eine blöde Frage sein, obwohl ich sicher bin, dass es viele andere Leute gibt, die von Zeit zu Zeit die gleiche Frage stellen. Ich möchte nur 100% sicher gehen, egal wie. Mit jQuery kennen wir alle das Wunderbare

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

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

Ich weiß, dass ich Folgendes kann:

window.onload="myFunction()";

... oder ich kann den Tag body verwenden:

<body onload="myFunction()">

... oder ich kann sogar versuchen, am Ende der Seite nach allem, aber das Ende body oder html Tag wie:

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

Was ist eine browserübergreifende (alte/neue) Methode, um eine oder mehrere Funktionen auf eine Weise wie jQueries $.ready() auszugeben?

1177
chris

Das Einfachste, was Sie tun können, wenn kein Framework vorhanden ist, das die gesamte Cross-Browser-Kompatibilität für Sie gewährleistet, ist, Ihren Code am Ende des Texts aufzurufen. Dies ist schneller auszuführen als ein onload -Handler, da nur darauf gewartet wird, dass das DOM bereit ist und nicht, dass alle Bilder geladen werden. 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 dies wirklich nicht auf diese Weise tun möchten und eine browserübergreifende Kompatibilität benötigen und nicht auf window.onload warten möchten, sollten Sie sich wahrscheinlich ansehen, wie ein Framework wie jQuery die Methode $(document).ready() implementiert. Es hängt ziemlich von den Fähigkeiten des Browsers ab.

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

Falls unterstützt, wird der Standard ausprobiert:

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

mit einem Fallback auf:

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

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

document.attachEvent("onreadystatechange", fn);

mit einem Fallback auf:

window.attachEvent("onload", fn);

Und es gibt einige Workarounds 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 jQueries .ready(), geschrieben in einfachem Javascript:

(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 auf GitHub unter https://github.com/jfriend00/docReady veröffentlicht

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

Funktionierende Implementierung und Testumgebung: http://jsfiddle.net/jfriend00/YfD3C/


Hier ist eine Zusammenfassung, wie es funktioniert:

  1. Erstellen Sie ein IIFE (sofort aufgerufener Funktionsausdruck), damit wir nicht öffentliche Statusvariablen haben können.
  2. Deklarieren Sie eine öffentliche Funktion docReady(fn, context)
  3. Wenn docReady(fn, context) aufgerufen wird, prüfen Sie, ob der Ready-Handler bereits ausgelöst hat. Wenn ja, planen Sie den neu hinzugefügten Rückruf so, dass er sofort ausgelöst wird, nachdem dieser Thread von JS mit setTimeout(fn, 1) abgeschlossen ist.
  4. Wenn der Ready-Handler noch nicht ausgelöst hat, fügen Sie diesen neuen Rückruf zur Liste der Rückrufe hinzu, die später aufgerufen werden sollen.
  5. Überprüfen Sie, ob das Dokument bereits fertig 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, installieren Sie sie jetzt.
  7. Wenn document.addEventListener vorhanden ist, installieren Sie Ereignisbehandlungsroutinen mit .addEventListener() sowohl für "DOMContentLoaded" als auch für "load" Ereignisse. Das "Laden" ist ein Sicherungsereignis für die Sicherheit und sollte nicht benötigt werden.
  8. Wenn document.addEventListener nicht vorhanden ist, installieren Sie Ereignishandler mit .attachEvent() für "onreadystatechange" - und "onload" -Ereignisse.
  9. Überprüfen Sie im Ereignis onreadystatechange, ob document.readyState === "complete" vorhanden ist, und rufen Sie in diesem Fall eine Funktion auf, um alle Ready-Handler auszulösen.
  10. Rufen Sie in allen anderen Ereignishandlern eine Funktion auf, um alle bereiten Handler auszulösen.
  11. Überprüfen Sie in der Funktion zum Aufrufen aller Ready-Handler eine Statusvariable, um festzustellen, ob wir bereits ausgelöst haben. Wenn ja, nichts tun. Wenn wir noch nicht aufgerufen wurden, durchlaufen Sie das Array der Ready-Funktionen und rufen Sie die einzelnen Funktionen in der Reihenfolge auf, in der sie hinzugefügt wurden. Setzen Sie ein Flag, um anzuzeigen, dass diese alle aufgerufen wurden, sodass sie nie mehr als einmal ausgeführt werden.
  12. Deaktivieren Sie das Funktionsarray, damit alle möglicherweise verwendeten Verschlüsse freigegeben werden können.

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

Wenn Sie docReady(fn) aufrufen, nachdem das Dokument bereits bereit ist, wird die Ausführung des Rückrufs geplant, sobald der aktuelle Ausführungsthread mit setTimeout(fn, 1) abgeschlossen ist. Auf diese Weise kann der aufrufende Code immer davon ausgehen, dass es sich um asynchrone Rückrufe handelt, die später aufgerufen werden, auch wenn dies später der Fall ist, sobald der aktuelle Thread von JS beendet ist und die Aufrufreihenfolge beibehalten wird.

1693
jfriend00

Ich möchte hier einige der möglichen Möglichkeiten zusammen mit einem reinen Javascript-Trick erwähnen, 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 dabei ist, wie vom rsprünglichen Autor erklärt, dass wir die Eigenschaft document.readyState überprüfen. Wenn es den String in enthält (wie in uninitialized und loading, setzen die ersten beiden DOM ready states von 5) wir ein Timeout und überprüfen es erneut. Andernfalls führen wir die übergebene Funktion aus.

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

Vielen Dank an Tutorialzine , dass sie dies in ihr Buch aufgenommen haben.

142
Ram Patra

Wenn Sie Vanille einfaches JavaScript ohne jQuery ausführen, 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!");
});

Welches AUCH KURZHAND so geschrieben werden könnte, welches jQuery läuft nach dem ready even tritt auf .

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

NICHT MIT UNTEN ZU VERwechseln (was nicht als DOM-Ready gedacht ist):

Verwenden Sie NICHT ein IIFE wie dieses, das 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 von Chrome Browser!)

123
Tom Stickel

Getestet in IE9 und den neuesten Versionen von 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 eine ziemlich einfache Entsprechung zu jQuery oder Dom Ready ohne Abwärtskompatibilität. Es muss wahrscheinlich weiter verfeinert werden. Getestet in den neuesten Versionen von Chrome, Firefox und IE (10/11) und sollte, wie bereits erwähnt, 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 ist für das asynchrone Laden von JS geschrieben, aber Sie möchten dieses Skript möglicherweise zuerst synchronisieren, es sei denn, Sie minimieren es. Ich habe es in der Entwicklung nützlich gefunden.

Moderne Browser unterstützen auch das asynchrone Laden von Skripten, was die Benutzererfahrung weiter verbessert. Die Unterstützung von Async bedeutet, dass mehrere Skripte gleichzeitig heruntergeladen werden können, während die Seite gerendert wird. Passen Sie einfach auf, wenn Sie von anderen asynchron geladenen Skripten abhängig sind, oder verwenden Sie einen Minifier oder so etwas wie browserify, um mit Abhängigkeiten umzugehen.

77
PhilT

Die guten Leute bei HubSpot haben eine Ressource, in der Sie reine Javascript-Methoden finden können, um eine Menge von 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'); });
19
Lorcan O'Neill

Ihre Methode (Platzieren des Skripts vor dem schließenden Body-Tag)

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

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

7
Kernel James

Ich bin nicht ganz sicher, was Sie fragen, aber vielleicht kann dies helfen:

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

}

Oder:

window.onload = main;

function main(){
    // Code. . .

}
5
Zak The Hat

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
Vitim.us

Hier ist eine bereinigte, nicht auswertbare Version von Ram-swaroop's "Funktioniert in allen Browsern" - Funktioniert in allen Browsern!

function onReady(yourMethod) {
  var readyStateCheckInterval = setInterval(function() {
    if (document && document.readyState === 'complete') { // Or 'interactive'
      clearInterval(readyStateCheckInterval);
      yourMethod();
    }
  }, 10);
}
// use like
onReady(function() { alert('hello'); } );

Es dauert jedoch weitere 10 ms, bis es ausgeführt wird. Hier ist eine kompliziertere Methode, die nicht ausgeführt werden sollte:

function onReady(yourMethod) {
  if (document.readyState === 'complete') { // Or also compare to 'interactive'
    setTimeout(yourMethod, 1); // Schedule to run immediately
  }
  else {
    readyStateCheckInterval = setInterval(function() {
      if (document.readyState === 'complete') { // Or also compare to 'interactive'
        clearInterval(readyStateCheckInterval);
        yourMethod();
      }
    }, 10);
  }
}

// Use like
onReady(function() { alert('hello'); } );

// Or
onReady(functionName);

Siehe auch So prüfen Sie, ob DOM ohne Framework bereit ist?.

3
rogerdpack

document.ondomcontentready=function(){} sollte den Trick machen, hat aber nicht die volle Browserkompatibilität.

Scheint, Sie sollten nur jQuery min verwenden

1
maxhud