Nach der Rückkehr in den Firefox-Verlauf wird JavaScript nicht ausgeführt

84

Wenn ich in Firefox die Schaltfläche "Zurück" verwende, um zu einer zuvor besuchten Seite zu gelangen, werden die Skripts auf dieser Seite nicht erneut ausgeführt .

Gibt es eine Korrektur / Problemumgehung , damit die Skripte beim zweiten Anzeigen der Seite erneut ausgeführt werden?

Bitte beachten Sie, dass ich dieselben Seiten in Google Chrome und Internet Explorer getestet habe und sie wie vorgesehen funktionieren.


Hier sind die Dateien und die Schritte, mit denen ich das Problem getestet habe:

(Navigieren Sie zu 0.html und klicken Sie, um zu 1.html zu gelangen. Klicken Sie auf die Schaltfläche Zurück.)

0.html

<html><body>
<script>
  window.onload = function() { alert('window.onload alert'); };
  alert('inline alert');
</script>
<a href="1.html">Click Me!</a>
</body></html>

1.html

<html><body>
<p>Go BACK!</p>
</body></html>
Patonza
quelle

Antworten:

91

Legen Sie eine leere Funktion fest, die in window.onunload aufgerufen werden soll:

window.onunload = function(){}; 

z.B

<html><body>
<script type="text/javascript">
  window.onload = function() { alert('window.onload alert'); };
  window.onunload = function(){};
  alert('inline alert');
</script>
<a href="1.html">Click Me!</a>
</body></html>

Quelle: http://www.firefoxanswer.com/firefox/672-firefoxanswer.html (Archivierte Version)

John Baber-Lucero
quelle
2
Danke, es funktioniert. Gibt es einen Hinweis darauf, was der Standard-Onunload-Handler tut? (zB überschreibe ich hier ein Standardverhalten?)
Patonza
Ok, danke, ich werde nachforschen.
Nochmals vielen
Weiß jemand, warum FireFox dies benötigt, während andere Browser dies nicht tun?
Pim Jäger
7
Sie überschreiben nichts, dies verhindert lediglich, dass Firefox die Seite im Back-Forward-Cache (bfcache) zwischenspeichert. developer.mozilla.org/en/DOM/window.onunload developer.mozilla.org/En/Using_Firefox_1.5_caching
Chris Haas
1
Obwohl es bfcache brechen sollte , scheint es sich leider immer noch an die vorherige Seite zu erinnern - insbesondere werden geladene Iframe-URLs beim Zurückladen erneut geladen, und wenn generierter Inhalt in den Frame eingefügt werden musste, scheint es keinen Crossbrowser zu geben Weg, um das neu zu aktualisieren.
NoBugs
76

Wenn ich in Firefox die Schaltfläche "Zurück" verwende, um zu einer zuvor besuchten Seite zu gelangen, werden die Skripts auf dieser Seite nicht erneut ausgeführt.

Das ist richtig und das ist gut so.

Wenn Sie in Firefox (und Safari und Opera) auf einen Link klicken, wird Ihre Seite nicht sofort zerstört, um zur nächsten zu gelangen. Es hält die Seite intakt und verbirgt sie lediglich vor der Ansicht. Wenn Sie auf die Schaltfläche "Zurück" klicken, wird die alte Seite wieder angezeigt, ohne dass das Dokument erneut geladen werden muss. Dies ist viel schneller, was zu reibungsloseren Seitenübergängen für den Benutzer führt.

Diese Funktion wird als bfcache bezeichnet .

Alle Inhalte, die Sie der Seite beim vorherigen Laden und Verwenden des Benutzers hinzugefügt haben, sind weiterhin vorhanden. Alle Ereignishandler, die Sie an Seitenelemente angehängt haben, werden weiterhin angehängt. Alle von Ihnen festgelegten Zeitüberschreitungen / Intervalle sind weiterhin aktiv. Es gibt also selten einen Grund, warum Sie wissen müssen, dass Sie versteckt und erneut gezeigt wurden. Es wäre falsch, onloadSkriptcode erneut aufzurufen oder einzubinden, da jede Bindung und Inhaltsgenerierung, die Sie in dieser Funktion durchgeführt haben, ein zweites Mal über denselben Inhalt ausgeführt wird, was möglicherweise katastrophale Folgen hat. (zB document.writein Inline-Skript würde die Seite völlig zerstören.)

Der Grund, warum das Schreiben in window.onunloadeinen Effekt hat, ist, dass die Browser, die bfcache implementieren, entschieden haben, dass - aus Gründen der Kompatibilität mit Seiten, die wirklich wissen müssen, wann sie verworfen werden - jede Seite, die Interesse daran hat, zu wissen, wann sie onunloadauftritt, den bfcache dazu veranlasst deaktiviert sein. Diese Seite wird frisch geladen, wenn Sie zurückkehren, anstatt aus dem bfcache abgerufen zu werden.

Wenn Sie also festlegen window.onunload= function() {};, brechen Sie den bfcache absichtlich ab. Dies führt dazu, dass Ihre Seiten nur langsam navigieren und nur als letztes Mittel verwendet werden sollten.

Wenn Sie wissen müssen, wann der Benutzer Ihre Seite verlässt oder zurückkehrt, ohne den bfcache durcheinander zu bringen, können Sie stattdessen die Ereignisse onpageshowund abfangen onpagehide:

window.onload=window.onpageshow= function() {
    alert('Hello!');
};
Bobince
quelle
3
Mein Problem ist, dass bfcache nicht die gesamte Seite zwischenspeichert, sodass ich js erneut ausführen muss, um verlorene Inhalte wiederherzustellen. Es könnte also in Ordnung sein, die ganze Seite zu verprügeln. Auf jeden Fall verwende ich nicht das Ereignis window.onload, sondern das Ereignis jQuery document.ready. Kennen Sie eine Möglichkeit, document.ready weiterhin zu verwenden und dieses Problem zu vermeiden?
Patonza
bfcache sollte im Allgemeinen die gesamte Seite so zurückgeben, wie sie war, als sie verlassen wurde. Welcher Inhalt fehlt nach der Rückkehr von der vorherigen Seite? (Testfall?) document.readyfunktioniert im Wesentlichen genauso wie window.onload(bei einigen Browsern handelt es sich ohnehin um dasselbe Ereignis).
Bobince
14
Das ist keine gute Sache, da das Javascript nicht erneut ausgeführt wird, wenn man bedenkt, dass es zwischengespeichert ist ... aber die Änderungen, die das Javascript zuvor vorgenommen hat, werden nicht zwischengespeichert. Wenn das Javascript ein Element beim Laden der Seite einblendet, wird es beim Besuch im Verlauf nicht erneut ausgeblendet ... sondern startet es erneut mit 0 Deckkraft und macht rückgängig, was das Javascript getan hat! Es muss ALLES ODER NICHTS sein. Sie müssen den vollständigen Status der Seite zwischenspeichern, nachdem das Javascript ausgeführt wurde, wenn Sie es im Cache präsentieren möchten, ohne das Javascript erneut auszuführen!
Jimbo Jonny
1
@ Jimbo: Testfall bitte. bfcache soll (und in jedem Fall, den ich je gesehen habe) den genauen Status des DOM über Verstecken / Anzeigen beibehalten. Ein eingeblendetes Element bleibt bei der Rückkehr zur Seite undurchsichtig, es sei denn, ein anderes Skript wird ausgeführt, um es erneut auszublenden.
Bobince
1
@bobince - Erstellen Sie ein Element mit einer CSS-Datei, indem Sie die Deckkraft auf Null setzen, und verwenden Sie dann etwas jQuery, um es in das Dokument einzufügen. Wenn Sie in den Verlauf zurückkehren, wird das Stylesheet-CSS (die Null) erneut angewendet, ohne die Deckkraft beizubehalten: 1, die der JS beim Einblenden dem Stilattribut hinzugefügt hat. Wenn Sie die Seite zum ersten Mal besuchen, wird das Element von Null auf 1 eingeblendet. Gehen Sie zu einer anderen Seite und schlagen Sie zurück und es wird einfach vollständig transparent dort sitzen.
Jimbo Jonny
23

Sie können die persistedEigenschaft des pageshowEreignisses überprüfen . Es wird beim ersten Laden der Seite auf false gesetzt. Wenn eine Seite aus dem Cache geladen wird, wird sie auf true gesetzt.

window.onpageshow = function(event) {
    if (event.persisted) {
        alert("From bfcache");
    }
};

Aus irgendeinem Grund verfügt jQuery im Ereignis nicht über diese Eigenschaft. Sie können es jedoch vom ursprünglichen Ereignis finden.

$(window).bind("pageshow", function(event) {
    if (event.originalEvent.persisted) {
        alert("From bfcache");
    }
});
Mika Tuupola
quelle
Vielen Dank, dass Sie sowohl Javascript- als auch JQuery-Versionen bereitgestellt haben! Sie haben dort am Ende eine enge Klammer verpasst (das ist kein Stöhnen!). Ich werde auch für andere bemerken, dass der IE- und Chrome-Bericht .persisted immer falsch ist, unabhängig davon.
Magnus Smith
Wie Magnus bemerkte, funktionierte dies in Chrome erst, als ich die if-Anweisung entfernte.
Justin
Dies funktionierte bei mir in Chrome 58.0.3029.110 (64-Bit) und FF 53.0.2 (64-Bit) ohne Änderungen.
kmoser
1

Verdrahten Sie ein "Onunload" -Ereignis, das nichts bewirkt:

<html><body>
<script type="text/javascript">
  window.onload = function() { alert('window.onload alert'); };
  window.onunload = function(){}; 
  alert('inline alert');
</script>
<a href="1.html">Click Me!</a>
</body></html>
Chris Haas
quelle
Ich bin mir nicht sicher, ob ich eine Abstimmung abgegeben habe. Es sieht so aus, als hätte jemand jede Antwort auf diese Frage
abgelehnt
Sie sollten Ihrer Antwort hinzufügen, dass durch Hinzufügen des Ereignisses onunload zu Ihrer Seite die zwischengespeicherte Seite tatsächlich vollständig deaktiviert wird. Dies führt nicht einfach dazu, dass der JS erneut ausgeführt wird, sondern erhöht auch die Serverlast um eine Stufe. Dies ist wirklich kein Vorschlag, leicht zu nehmen, dies sollte sorgfältig abgewogen werden.
Dreagan
@dreagan, dies deaktiviert den bfcache, aber nicht unbedingt den HTTP-Cache. Der HTTP-Cache hat eine ganze Reihe anderer Regeln. Wenn Sie dort einen serverseitigen Ruhezustand aktivieren, sollten Sie dies beim Zurückklicken bemerken. Mozilla spricht darüber in seiner dritten Frage in den FAQ für BFCache .
Chris Haas
Ich habe über den BFcache gesprochen, hätte das spezifizieren sollen. Das bedeutet nicht, dass Sie einen solchen Vorschlag machen sollten, ohne das OP über die Konsequenzen zu informieren. Eine Alternative wäre, das Ereignis onpopstate zu verwenden, um zu versuchen, das Javascript erneut auszulösen.
Dreagan
Ich weiß immer noch nicht, ob ich verstehe. Warum sollte "die Serverlast um eine Stufe steigen", wenn der lokale Bfcache des Clients umgangen wird? Ja, das DOM muss neu erstellt werden, aber der HTML-Code sollte Teil des HTTP-Cache des Clients sein. Ja, zusätzliche Ressourcen müssen neu geladen werden, diese sollten jedoch auch Teil des HTTP-Cache des Clients sein. Als onpopstatediese Frage vor fast fünf Jahren gestellt wurde, war dieses Ereignis noch relativ neu und die Browserunterstützung war sehr inkonsistent
Chris Haas
1

Soweit ich weiß, feuert Firefox kein onLoadEreignis auf dem Rücken ab.

Es sollte stattdessen onFocus auslösen, basierend auf diesem Link hier .

systempuntoout
quelle
Getestet und windows.onfocus wird tatsächlich aufgerufen, auch ohne den leeren window.onunload-Handler zu setzen. Das Einstellen von Onunload ist eine etwas schönere Problemumgehung, aber .onfocus sollte auch in Ordnung sein. Danke :)
Patonza
1

Eine einfache Möglichkeit, eine Seite dazu zu bringen, JavaScript auszuführen, wenn der Benutzer mithilfe des Browserverlaufs zurück zu dieser Seite navigiert, ist das OnPopState-Ereignis. Wir verwenden dies, um das Video auf unserer Homepage ( https://fynydd.com ) anzuhalten und wiederzugeben .

window.onpopstate = function() {

    // Do stuff here...
};
Michael A.
quelle
0

Für einige Fälle wie Ajax-Operationen kann der URL-Änderungs-Listener verwendet werden

$(window).on('hashchange', function() {
        ....
});
Dompteur
quelle