Gibt es ein browserübergreifendes Onload-Ereignis, wenn Sie auf die Schaltfläche "Zurück" klicken?

185

Bei allen gängigen Browsern (außer IE) wird das JavaScript- onloadEreignis nicht ausgelöst, wenn die Seite aufgrund einer Zurück-Schaltfläche geladen wird. Es wird nur ausgelöst, wenn die Seite zum ersten Mal geladen wird.

Kann mich jemand auf einen browserübergreifenden Beispielcode (Firefox, Opera, Safari, IE, ...) verweisen, der dieses Problem löst? Ich bin mit der pageshowVeranstaltung von Firefox vertraut, aber leider implementieren weder Opera noch Safari dies.

Rechnung
quelle
6
Dies ist kein Problem - es ermöglicht das schnelle Laden der Webseite, wenn der Benutzer die Zurück-Taste drückt. Siehe meine Antwort unten für Details. Die hier vorgeschlagenen Problemumgehungen machen die Webseite für den Benutzer ärgerlicher, da das Navigieren vorwärts / rückwärts langsamer ist.
Nickolay
2
@romkyns: Ihr Kommentar hat nichts mit dieser Frage zu tun. Wenn Browser den JS / DOM-Status nicht wiederherstellen, lösen sie das Ladeereignis aus.
Nickolay
iOS 5+ Verlauf zurück Schaltfläche hier gelöst stackoverflow.com/a/12652160/1090395
Mladen Janjetovic

Antworten:

117

Leute, ich habe festgestellt, dass JQuery nur einen Effekt hat: Die Seite wird neu geladen, wenn die Zurück-Taste gedrückt wird. Dies hat nichts mit " bereit " zu tun .

Wie funktioniert das? Nun, JQuery fügt einen Onunload- Ereignis-Listener hinzu.

// http://code.jquery.com/jquery-latest.js
jQuery(window).bind("unload", function() { // ...

Standardmäßig macht es nichts. Aber irgendwie scheint dies ein Neuladen in Safari, Opera und Mozilla auszulösen - egal was der Event-Handler enthält.

[ edit (Nickolay) : Hier ist, warum es so funktioniert: webkit.org , developer.mozilla.org . Bitte lesen Sie diese Artikel (oder meine Zusammenfassung in einer separaten Antwort unten) und überlegen Sie, ob Sie dies wirklich tun müssen, damit Ihre Seite für Ihre Benutzer langsamer geladen wird.]

Kannst du es nicht glauben? Versuche dies:

<body onunload=""><!-- This does the trick -->
<script type="text/javascript">
    alert('first load / reload');
    window.onload = function(){alert('onload')};
</script>
<a href="http://stackoverflow.com">click me, then press the back button</a>
</body>

Bei Verwendung von JQuery werden ähnliche Ergebnisse angezeigt.

Vielleicht möchten Sie mit diesem ohne Onunload vergleichen

<body><!-- Will not reload on back button -->
<script type="text/javascript">
    alert('first load / reload');
    window.onload = function(){alert('onload')};
</script>
<a href="http://stackoverflow.com">click me, then press the back button</a>
</body>
user123444555621
quelle
1
Sehr schön .. obwohl dies eine undokumentierte Funktion / ein undokumentierter Fehler ist und möglicherweise in zukünftigen Versionen des Browsers einfach nicht mehr funktioniert, ist es dennoch interessant.
Wadih M.
3
Dies funktioniert auch (vergessen Sie nicht den Teil onunload = "", sonst funktioniert er nicht auf ff3): <body onload = "alert ('onload');" onunload = "">
Wadih M.
3
Dies liegt daran, dass der Browser davon ausgeht, dass die Seite nicht zwischengespeichert werden kann, wenn sie über einen onunloadHandler verfügt (die Seite hat bereits alles zerstört; warum sie zwischenspeichern?).
Casey Chu
14
Die Antwort scheint in modernen Browsern nicht zu funktionieren - eingecheckt in Chrome und Opera
Andrew
10
es funktioniert nicht in iPad Safari ... bitte markieren Sie dies als Antwort
xus
74

Einige moderne Browser (Firefox, Safari und Opera, aber nicht Chrome) unterstützen den speziellen "Zurück / Vorwärts" -Cache (ich nenne ihn bfcache, ein von Mozilla erfundener Begriff), der beim Navigieren des Benutzers zurück verwendet wird. Im Gegensatz zum regulären (HTTP-) Cache wird der vollständige Status der Seite (einschließlich des Status von JS, DOM) erfasst. Dadurch kann die Seite schneller und genau so neu geladen werden, wie der Benutzer sie verlassen hat.

Das loadEreignis soll nicht ausgelöst werden, wenn die Seite aus diesem bfcache geladen wird. Wenn Sie beispielsweise Ihre Benutzeroberfläche im Handler "Laden" erstellt haben und das Ereignis "Laden" beim ersten Laden einmal ausgelöst wurde und das zweite Mal, wenn die Seite erneut aus dem bfcache geladen wurde, die Seite mit endet doppelte UI-Elemente.

Dies ist auch der Grund, warum das Hinzufügen des Handlers "Entladen" verhindert, dass die Seite im bfcache gespeichert wird (wodurch die Navigation langsamer wird). Der Handler zum Entladen kann Bereinigungsaufgaben ausführen, wodurch die Seite möglicherweise nicht mehr funktioniert.

Für Seiten, die wissen müssen, wann sie weg / zurück navigiert werden, unterstützen Firefox 1.5+ und die Version von Safari mit dem Fix für Fehler 28758 spezielle Ereignisse namens "pageshow" und "pagehide".

Verweise:

Nickolay
quelle
Das ist sehr cool. Ich bin derzeit in einer Situation, in der meine Dom-Manipulationen nicht im bfcache gespeichert zu sein scheinen. Gibt es Situationen, in denen Sie das erwarten könnten?
Benson
1
@Benson: Die möglichen Gründe, warum Firefox Ihre Seite nicht in bfcache speichert, sind auf der dev.mo-Seite aufgeführt, auf die ich verlinkt habe. Ich glaube nicht, dass es möglich ist, die Seite in bfcache zu speichern, aber ein bestimmter DOM-Status wird nicht gespeichert.
Nickolay
Nickolay, ich zögere, dass Sie ein Neuladen erzwingen und die gute Arbeit des bfcache rückgängig machen. Aber gibt es eine andere Möglichkeit, den Dom der Seite im bfcache zu aktualisieren? Stellen Sie sich zum Beispiel die Situation vor, in der ich von einer Seite mit einer Liste von Nachrichten zu einer von ihnen wechsle und wenn ich "zurück" gehe, möchte ich, dass sich die Anzeige für Lesen / Ungelesen ändert. Wie geht das, ohne die Seite neu zu laden?
Greg
@ Greg: Du meinst als Entwickler die Seite kontrollieren? Starten Sie eine Ajax-Anfrage von einem 'Pageshow'-Listener.
Nickolay
Irgendwelche Ideen zur Verwendung von jQuery UND zur schnellen Unterstützung von bfcache?
Alex Black
31

Ich stieß auf ein Problem, das mein js nicht ausführte, als der Benutzer vorwärts oder rückwärts geklickt hatte. Ich wollte zuerst verhindern, dass der Browser zwischengespeichert wird, aber dies schien nicht das Problem zu sein. Mein Javascript wurde so eingestellt, dass es ausgeführt wird, nachdem alle Bibliotheken usw. geladen wurden. Ich habe diese mit dem Ereignis readyStateChange überprüft.

Nach einigen Tests stellte ich fest, dass der readyState eines Elements auf einer Seite, auf die zurück geklickt wurde, nicht "geladen", sondern "vollständig" ist. Das Hinzufügen || element.readyState == 'complete'zu meiner bedingten Aussage löste meine Probleme.

Ich dachte nur, ich würde meine Erkenntnisse teilen, hoffentlich helfen sie jemand anderem.

Der Vollständigkeit halber bearbeiten

Mein Code sah wie folgt aus:

script.onreadystatechange(function(){ 
   if(script.readyState == 'loaded' || script.readyState == 'complete') {
      // call code to execute here.
   } 
});

Im obigen Codebeispiel war die Skriptvariable ein neu erstelltes Skriptelement, das dem DOM hinzugefügt wurde.

Brian Heese
quelle
7
Wo hast du das hinzugefügt? Und wie haben Sie etwas zum Feuern gebracht, nachdem der Benutzer zurückgeschlagen hat? Bitte zeigen Sie uns einen Code!
Keerigan
Was meinst du mit "meine bedingte Aussage"?
Phillip Senn
1
@Phillip Eine bedingte Anweisung ist eine if-Anweisung.
Brian Heese
22

OK, hier ist eine endgültige Lösung, die auf der ursprünglichen Lösung von ckramer und dem Beispiel von palehorse basiert und in allen Browsern, einschließlich Opera, funktioniert. Wenn Sie history.navigationMode auf "kompatibel" setzen, wird die Bereitschaftsfunktion von jQuery sowohl in Opera als auch in den anderen gängigen Browsern für die Schaltflächen "Zurück" ausgelöst.

Diese Seite enthält weitere Informationen .

Beispiel:

history.navigationMode = 'compatible';
$(document).ready(function(){
  alert('test');
});

Ich habe dies in Opera 9.5, IE7, FF3 und Safari getestet und es funktioniert in allen.

Rechnung
quelle
2
Natürlich ist es eine Weile her (ungefähr 5,5 Jahre), aber es ist erwähnenswert, dass Ihr Link tot ist.
Jeff
2
Diese Lösung funktioniert bei mir nicht. Ich habe dieses Problem in der neuesten Firefox (45.0.1)
Armin
6

Ich konnte die obigen Beispiele nicht zum Laufen bringen. Ich wollte einfach eine Aktualisierung bestimmter geänderter Div-Bereiche auslösen, wenn ich über die Schaltfläche "Zurück" zur Seite zurückkehre. Der Trick, den ich benutzte, bestand darin, ein verstecktes Eingabefeld (als "Dirty Bit" bezeichnet) auf 1 zu setzen, sobald sich die Div-Bereiche vom Original geändert hatten. Das versteckte Eingabefeld behält seinen Wert tatsächlich bei, wenn ich zurückklicke, sodass ich beim Laden nach diesem Bit suchen kann. Wenn es eingestellt ist, aktualisiere ich die Seite (oder aktualisiere einfach die Divs). Beim ursprünglichen Laden ist das Bit jedoch nicht gesetzt, sodass ich keine Zeit damit verschwenden muss, die Seite zweimal zu laden.

<input type='hidden' id='dirty'>

<script>
$(document).ready(function() {
  if ($('#dirty').val()) {
    // ... reload the page or specific divs only
  }
  // when something modifies a div that needs to be refreshed, set dirty=1
  $('#dirty').val('1');
});
</script>

Und es würde richtig ausgelöst, wenn ich auf den Zurück-Button klickte.

Thorie
quelle
3
Während dies in Firefox nicht funktioniert, denke ich, dass es eine listige Möglichkeit ist, mit der Situation in IE / Chrome umzugehen, in der die Persistenz des verborgenen Feldes sehr nützlich ist. Ich habe Ihren Trick und auch das "Pageshow" -Ereignis verwendet, damit ich alle Hauptbrowser abdecken kann.
Magnus Smith
Welcher Browser funktioniert nicht mit Pageshow?
Justin
4

Wenn ich mich richtig erinnere, bedeutet das Hinzufügen eines unload () -Ereignisses, dass die Seite nicht zwischengespeichert werden kann (im Vorwärts- / Rückwärts-Cache) - da sich der Status ändert / ändern kann, wenn der Benutzer weg navigiert. Es ist also nicht sicher, den Status der Seite in letzter Sekunde wiederherzustellen, wenn Sie durch Navigieren durch das Verlaufsobjekt zu dieser Seite zurückkehren.


quelle
4

Ich dachte, dies wäre für "onunload", nicht für das Laden von Seiten, da wir nicht über das Auslösen eines Ereignisses sprechen, wenn wir auf "Back" klicken? $ document.ready () ist für Ereignisse gedacht, die beim Laden der Seite gewünscht werden, unabhängig davon, wie Sie zu dieser Seite gelangen (z. B. umleiten, den Browser direkt zur URL öffnen usw.), und nicht, wenn Sie auf "Zurück" klicken, es sei denn, Sie sprechen Informationen darüber, was auf der vorherigen Seite ausgelöst werden soll, wenn es erneut geladen wird. Und ich bin nicht sicher, ob die Seite nicht zwischengespeichert wird, da ich festgestellt habe, dass Javascripts immer noch vorhanden sind, selbst wenn $ document.ready () darin enthalten ist. Wir mussten Strg + F5 drücken, wenn wir unsere Skripte mit diesem Ereignis bearbeiten, wenn wir sie überarbeiten und die Ergebnisse auf unseren Seiten testen möchten.

$(window).unload(function(){ alert('do unload stuff here'); }); 

ist das, was Sie für ein Onunload-Ereignis wünschen, wenn Sie auf "Zurück" klicken und die aktuelle Seite entladen. Dies wird auch ausgelöst, wenn ein Benutzer das Browserfenster schließt. Das klang eher nach dem, was gewünscht wurde, auch wenn ich mit den Antworten von $ document.ready () zahlenmäßig unterlegen bin. Grundsätzlich besteht der Unterschied zwischen einem Ereignis, das auf der aktuellen Seite beim Schließen ausgelöst wird, oder dem Ereignis, das beim Klicken auf "Zurück" beim Laden geladen wird. Getestet in IE 7 gut, kann nicht für die anderen Browser sprechen, da sie nicht erlaubt sind, wo wir sind. Dies könnte jedoch eine andere Option sein.

Tom
quelle
4

Ich kann ckramer bestätigen, dass das Ready-Ereignis von jQuery in IE und FireFox funktioniert. Hier ist ein Beispiel:

<html>
<head>
    <title>Test Page</title>
    <script src="http://code.jquery.com/jquery-latest.js" type="text/javascript"></script>
    <script type="text/javascript">
            $(document).ready(function () {
               var d = new Date();
               $('#test').html( "Hi at " + d.toString() );
            });
    </script>
</head>
<body>
    <div id="test"></div>
    <div>
        <a href="http://www.google.com">Go!</a>
    </div>
</body>
</html>
Palehorse
quelle
4

Für die Leute, die nicht die gesamte jquery-Bibliothek nutzen wollen, habe ich die Implementierung in separatem Code extrahiert. Es ist nur 0,4 KB groß.

Den Code finden Sie zusammen mit einem deutschen Tutorial in diesem Wiki: http://www.easy-coding.de/wiki/html-ajax-und-co/onload-event-cross-browser-kompatibler-domcontentloaded.html

Torben Brodt
quelle
1
Lone Link wird als schlechte Antwort angesehen (siehe FAQ ), da es für sich genommen bedeutungslos ist und nicht garantiert wird, dass die Zielressource in Zukunft am Leben bleibt . Es wäre vorzuziehen , die wesentlichen Teile der Antwort hier aufzunehmen und den Link als Referenz bereitzustellen.
j0k
3

jQuerys Ready- Event wurde für genau diese Art von Problem erstellt. Vielleicht möchten Sie sich mit der Implementierung befassen, um zu sehen, was unter der Decke vor sich geht.

ckramer
quelle
6
Eine lange Zeit später readyscheint in Firefox nicht ausgelöst zu werden, wenn die Schaltfläche Zurück verwendet wird. Siehe auch Nickolays Antwort .
Arjan
2

Bill, ich wage es, Ihre Frage zu beantworten, bin mir jedoch mit meinen Vermutungen nicht 100% sicher. Ich denke, dass andere als IE-Browser, wenn Benutzer zu einer Seite im Verlauf weitergeleitet werden, nicht nur die Seite und ihre Ressourcen aus dem Cache laden, sondern auch den gesamten DOM-Status (Lesesitzung) dafür wiederherstellen. Der IE führt keine DOM-Wiederherstellung durch (oder zumindest nicht), und daher scheint das Onload-Ereignis für eine ordnungsgemäße Seiteninitialisierung dort erforderlich zu sein.

Sergey Ilinsky
quelle
2

Ich habe die Lösung von Bill mit $ (document) .ready ausprobiert ... aber zuerst hat es nicht funktioniert. Ich habe festgestellt, dass das Skript nicht funktioniert, wenn es nach dem HTML-Abschnitt platziert wird. Wenn es der Kopfabschnitt ist, funktioniert es aber nur im IE. Das Skript funktioniert in Firefox nicht.

Johann
quelle
1

OK, ich habe es versucht und es funktioniert in Firefox 3, Safari 3.1.1 und IE7, aber nicht in Opera 9.52.
Wenn Sie das unten gezeigte Beispiel verwenden (basierend auf dem Beispiel von palehorse), wird beim ersten Laden der Seite ein Warnfeld angezeigt. Wenn Sie dann zu einer anderen URL wechseln und dann auf die Schaltfläche Zurück klicken, um zu dieser Seite zurückzukehren, wird in Opera kein Popup-Fenster mit Warnmeldungen angezeigt (in den anderen Browsern).

Wie auch immer, ich denke, das ist vorerst nah genug. Vielen Dank an alle!

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Untitled Document</title>
<meta http-equiv="expires" content="0">
<script src="jquery.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready( 
                    function(){
                      alert('test');
                    }
                 );
</script>
</head>
<body>
<h1>Test of the page load event and the Back button using jQuery</h1>
</body>
</html>
Rechnung
quelle
1

Unload - Ereignis funktioniert gut nicht auf IE 9. Ich versuchte es mit Load - Ereignisse (onload ()), es funktioniert gut auf IE 9 und FF5 .

Beispiel:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
    jQuery(window).bind("load", function() {
        $("[name=customerName]").val('');
    });
</script>
</head>
<body>
    <h1>body.jsp</h1>
    <form action="success.jsp">
        <div id="myDiv">

        Your Full Name: <input name="yourName" id="fullName"
            value="Your Full Name" /><br> <br> <input type="submit"><br>

        </div>

    </form>
</body>
</html>
Mallesham
quelle
0

Ich habe eine HTML-Vorlage verwendet. In der Datei custom.js dieser Vorlage gab es eine Funktion wie die folgende:

    jQuery(document).ready(function($) {

       $(window).on('load', function() {
          //...
       });

    });

Diese Funktion funktionierte jedoch nicht, wenn ich nach dem Aufrufen einer anderen Seite zurück gehe.

Also habe ich es versucht und es hat funktioniert:

    jQuery(document).ready(function($) {
       //...
    });

   //Window Load Start
   window.addEventListener('load', function() {
       jQuery(document).ready(function($) {
          //...
       });
   });

Jetzt habe ich 2 "Bereit" -Funktion, aber es gibt keinen Fehler und die Seite funktioniert sehr gut.

Trotzdem muss ich erklären, dass es unter Windows 10 - Opera v53 und Edge v42 getestet wurde, aber keine anderen Browser. Denken Sie daran ...

Hinweis: Die jquery-Version war 3.3.1 und die Migrationsversion war 3.0.0

bafsar
quelle