Wann genau wird der Rückruf $ (document) .ready ausgeführt?

74

Angenommen, wir hängen einen .click()Handler an ein anchor ( <a>) -Tag im $(document).readyRückruf an. Dieser Handler bricht die Standardaktion (nach href) ab und zeigt eine Warnung an.

Ich würde gerne wissen, wann genau der Rückruf ausgeführt wird und ob der Benutzer auf den Anker klicken kann (das Dokument wurde im Browser angezeigt), aber das Ereignis wurde noch nicht angehängt.

Hier sind verschiedene HTML-Seiten, die einen Anker enthalten, aber die Reihenfolge der Aufnahme der Skripte ist unterschiedlich. Was ist der Unterschied (wenn überhaupt) zwischen ihnen? Verhalten sich verschiedene Browser unterschiedlich?

Seite 1:

<html>
<head>
    <title>Test 1</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
    <script type="text/javascript">
    $(function() {
        $('a').click(function() {
            alert('overriding the default action');
            return false;
        });
    });
    </script>
</head>
<body>
    <a href="http://www.google.com">Test</a>
</body>
</html>

Seite 2:

<html>
<head>
    <title>Test 1</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
</head>
<body>
    <a href="http://www.google.com">Test</a>
    <script type="text/javascript">
    $(function() {
        $('a').click(function() {
            alert('overriding the default action');
            return false;
        });
    });
    </script>
</body>
</html>

Seite 3:

<html>
<head>
    <title>Test 1</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
    <a href="http://www.google.com">Test</a>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
    <script type="text/javascript">
    $(function() {
        $('a').click(function() {
            alert('overriding the default action');
            return false;
        });
    });
    </script>
</body>
</html>

Ist es also möglich, dass ein Benutzer hrefdurch Klicken auf den Anker zum weitergeleitet wird und die Warnung nie sieht (wobei der Fall von deaktiviertem Javascript natürlich ignoriert wird)? Könnte dies in einem der von mir angegebenen Beispiele passieren?

Ich muss lediglich sicherstellen, dass der clickEreignishandler an den Anker angehängt wurde, bevor der Benutzer auf diesen Anker klicken kann. Ich weiß, dass ich ein leeres bereitstellen hrefund es dann schrittweise in Javascript verbessern kann, aber dies ist eine allgemeinere Frage.

Was passiert, wenn der HTML-Code schnell vom Webserver generiert wird, die Abfrage der jquery-Bibliothek jedoch einige Zeit dauert, um von einem entfernten Server abgerufen zu werden? Wird dies mein Szenario beeinflussen? Wie ist die Reihenfolge der Aufnahme der Skripte im Vergleich zum Laden des DOM? Könnten sie parallel durchgeführt werden?

Darin Dimitrov
quelle

Antworten:

59

Beispiel 3 hat die höchste Chance, dass der Benutzer auf den Link klicken kann, ohne dass sich der Handler selbst angehängt hat. Da Sie die jQuery-Bibliothek nach dem Rendern des Links laden , wenn die Server von Google etwas langsam sind (oder die DNS-Suche etwa eine Sekunde dauert) oder der Computer des Benutzers jQuery nur langsam verarbeitet, verfügt der Link nicht über einen Klick-Handler angehängt, wenn der Benutzer versucht, darauf zu klicken.

Eine andere Situation, in der dies passieren kann, ist, wenn Sie eine sehr große oder langsam ladende Seite haben und dieser Link oben ist. Dann ist das DOM möglicherweise nicht vollständig bereit, wenn Teile davon sichtbar sind. Wenn Sie auf ein solches Problem stoßen, ist es am sichersten :

  1. Laden Sie jQuery in head(Beispiel 1 oder 2)
  2. Fügen Sie das <a>Klickereignis unmittelbar nach dem Element hinzu, jedoch nicht in einem DOMReady-Rückruf. Auf diese Weise wird es sofort aufgerufen und wartet nicht auf den Rest des Dokuments.

Sobald ein Element gerendert wurde, kann es aus dem DOM abgerufen werden, und anschließend kann jQuery darauf zugreifen:

<a href="http://www.google.com">Test</a>
<script type="text/javascript>
    // No (document).ready is needed. The element is availible
    $('a').click(function() {
        alert('overriding the default action');
        return false;
    });
</script>

Zusätzlich auf user384915 Kommentar Gebäude, wenn die Aktion auf JavaScript vollständig abhängig ist, dann nicht einmal die es als Teil des HTML machen, fügen Sie es nach jQuery ist fertig:

<script type="text/javascript">
jQuery(function($){
   $("<a />", { 
      style: "cursor: pointer", 
      click: function() {
        alert('overriding the default action');
        return false;
      },
      text: "Test"
   }).prependTo("body");
});
</script>
Doug Neiner
quelle
15

Sie haben hier ein paar verschiedene Fragen

Wann genau wird der Rückruf $ (document) .ready ausgeführt?

Es wird ausgeführt, sobald das DOM vollständig geladen ist. NICHT, wenn alles (wie Bilder) fertig heruntergeladen ist, wie es .load () wäre. Es ist (im Allgemeinen) davor, im Grunde ist es, wenn die Seite selbst erstellt wird.

Ich würde gerne wissen, wann genau der Rückruf ausgeführt wird

Wenn es angeklickt wird.

Ist es dem Benutzer möglich, auf den Anker zu klicken (das Dokument wurde im Browser angezeigt), aber das Ereignis wurde noch nicht angehängt.

Ja, es ist möglich. Wenn Sie es jedoch in .ready () einfügen, haben Sie die beste Chance, dass dies nicht der Fall ist. Es gibt nur zwei Möglichkeiten, um "sicherer" zu sein, dass dies nicht der Fall ist. Diese verwenden tatsächlich den 'onclick' auf den Link selbst und setzen das Javascript direkt hinter den Link (und nicht in .ready ()), so dass es unmittelbar nach dem Erstellen des Links ausgeführt wird.

Es gibt auch keinen Unterschied zwischen der Funktionsweise der beiden von Ihnen bereitgestellten Codebeispiele. Im zweiten Fall müssen Sie den Code jedoch nicht in .ready () einfügen, da er nach dem Link vorhanden ist. Er wird immer ausgeführt, nachdem der Link erstellt wurde. Wenn Sie es aus .ready () entfernen, ist dies die erste der beiden oben beschriebenen Möglichkeiten.

Anstatt 'return false' zu setzen; In Ihrem Rückruf ist es besser, .preventDefault () und .stopPropagation () zu verwenden. Hier können Sie angeben, ob Sie die Standardaktion verhindern oder das Sprudeln des Ereignisses verhindern möchten oder beides.

Matt Evanoff
quelle
Sie sagen also, dass der einzige Weg, um das zu erreichen, wonach ich suche (haben Sie die Garantie, dass der Benutzer vor der Weiterleitung eine Warnung sieht), darin besteht, onclickden clickHandler direkt nach dem Link zu verwenden oder anzuhängen (nicht zu verwenden $(document).ready)?
Darin Dimitrov
Die Beispiele unterscheiden sich je nachdem, ob die Ausgabepufferung aktiviert ist oder ob eine Chunk-Codierung verwendet wird.
Gblazex
Welches der drei Beispiele eignet sich am besten für mein Ziel, wenn die Pufferung aktiviert ist? Was ist mit Chunked-Codierung?
Darin Dimitrov
2
Die Verwendung von onclick wäre der einzige Weg, um sicher zu sein. Wenn Sie .ready () verwenden, ist es höchst unwahrscheinlich, dass es nicht passiert, und wenn es nicht so schlimm ist, ist es wahrscheinlich am besten, einen anderen Weg zu finden, um das zu tun, was Sie gerade tun. Denken Sie daran, dass nicht jeder Javascript aktiviert hat. Daher ist es sehr gut möglich, dass jemand auf diesen Link klickt und die Standardaktion ausführt.
Matt Evanoff
2

Es hängt von vielen Dingen ab. Wenn Sie beispielsweise eine Chunk-Codierung haben, ist es möglich, dass ein Benutzer einen Chunk erhält. Da das Dokument jedoch noch nicht fertig ist, wird der Listener nicht angehängt.

Das jQuery ready-Ereignis ist das DOMContentLoaded- Ereignis in W3C-kompatiblen Browsern (standardisiert in der HTML5-Spezifikation) und einige Alternativen dazu in anderen (wie Readystate im IE).

DOMContentLoaded (MDC)

Wird am Dokumentobjekt der Seite ausgelöst, wenn das Parsen des Dokuments abgeschlossen ist. Wenn dieses Ereignis ausgelöst wird, ist das DOM der Seite bereit.

Da dies vor dem Rendern geschieht, wird davon ausgegangen, dass ein nach diesem Ereignis ausgeführter Rückruf die Benutzerinteraktion auf einer nicht bereitstehenden Seite verhindern kann.

Aber wie Peter Michaux in seinem Artikel aufgrund der unterschiedlichen Art und Weise, wie Browser dieses Ereignis implementieren, hervorhob, "ist eine robuste Technik zur frühen Belebung in den vier großen Browsern nicht möglich."

Ich würde also sagen, dass Sie sich nicht zu 100% auf ein jQuery-fähiges Ereignis verlassen können, aber die meiste Zeit wird es gut funktionieren .

gblazex
quelle
2

In YUI gibt es die Methoden onContentReady()und onAvailable(). Leider gibt es in jQuery kein Äquivalent dazu. Es gibt jedoch ein Plugin, das von ihnen inspiriert wurde:

http://www.thunderguy.com/semicolon/2007/08/14/elementready-jquery-plugin/

Auf diese Weise können Sie die Ereignisse an den Anker binden, bevor das DOM vollständig geladen ist.

Ken Earley
quelle
1

Ihr drittes Beispiel bietet die größte Chance, dass der Benutzer klickt, ohne dass der Override-Handler angehängt wurde. Der Browser lädt im Allgemeinen die einzelnen Dateien herunter und analysiert sie, <script>bevor er zum nächsten übergeht . Sie beziehen jQuery von einer externen Quelle (Google) ein, die zwar wahrscheinlich zuverlässig ist, aber möglicherweise nicht verfügbar ist oder nur langsam geladen wird. Sie haben beide <script>Blöcke am Ende Ihres Dokuments <body>, sodass die vorherigen Bereiche der Seite wahrscheinlich bereits heruntergeladen und auf dem Bildschirm gerendert wurden, während diese beiden letzten Skripte verarbeitet werden. Während dieser Ansatz empfohlen wird, um dem Benutzer eine reaktionsschnelle Erfahrung beim Laden von Seiten zu bieten, könnten sie in diesem unsicheren Zeitraum klicken, und natürlich wäre der Override-Handler noch nicht angehängt worden.

Es ist ein interessanter YUIblog Artikel über Skripte und Ladereihenfolge hier .

Ken Redler
quelle
0

Natürlich ist es möglich, die Warnmeldung zu "betrügen" (auch wenn Javascript aktiviert ist). Versuchen Sie, den Link in das URL-Feld zu ziehen, und Sie werden sehen, dass er ohne diese Warnung ausgeführt wird. Dies ist besonders problematisch, wenn der Link die Löschaktion auslöst.

Über das document.ready Rückruf - Ich habe auch ein solches Problem. Lassen Sie mich erklären. Wir führen ein Projekt durch, bei dem alle Formulare in Popups angezeigt werden (jQuery-Fenster). Wenn das Popup (vorerst) geschlossen wird, wird die Seite neu geladen, und ich hatte Fälle, in denen ich zu einem anderen Bildschirm umgeleitet wurde, anstatt ein neues Popup zu öffnen.

Stimmen Sie dem Benutzer 384915 voll und ganz zu, wenn Sie Javascript direkt in das onClick-Ereignis oder noch besser in das href-Tag einfügen.

Nik Chankov
quelle