Ajax-, Zurück-Button- und DOM-Updates

113

Wenn Javascript das DOM auf Seite A ändert, navigiert der Benutzer zu Seite B und drückt dann auf die Schaltfläche Zurück, um zur Seite A zurückzukehren. Alle Änderungen am DOM von Seite A gehen verloren und dem Benutzer wird die Version angezeigt, die ursprünglich vom Server abgerufen wurde.

Dies funktioniert auf Stackoverflow, Reddit und vielen anderen beliebten Websites. (Versuchen Sie, dieser Frage einen Testkommentar hinzuzufügen, navigieren Sie dann zu einer anderen Seite und klicken Sie auf die Schaltfläche "Zurück", um zurückzukehren. Ihr Kommentar ist "weg".)

Dies ist sinnvoll, aber einige Websites (apple.com, basecamphq.com usw.) zwingen den Browser irgendwie dazu, dem Benutzer den neuesten Status der Seite zu liefern. (Gehen Sie zu http://www.apple.com/ca/search/?q=ipod , klicken Sie oben auf den Link "Downloads sagen" und dann auf die Schaltfläche "Zurück" - alle DOM-Updates bleiben erhalten.)

Woher kommt die Inkonsistenz?

lubos hasko
quelle
Interessanterweise erinnert sich Apple an den Status, ohne den Hash zu ändern. Hmmm
James
Apple sieht aus wie sie nur das Zwischenspeichern von Antworten manipulieren
BigBlondeViking
Wie andere bereits vorgeschlagen haben, hat dies nichts mit Javascript oder Ajax zu tun. Sie sollten diese Tags entfernen, um korrekte Antworten zu erhalten.
BYK
Das Apple-Beispiel ist schlecht. Wenn Sie einen Suchbereich [z. B. Produkte] kontrahieren, auf Ihren Link klicken und dann zurück drücken, bleibt das DOM nicht erhalten. Sie suchen nach einer Hash-Lösung, die viele vorgeschlagen haben.
BigBlondeViking
Wenn ich auf die Schaltfläche "Zurück" drücke, kann sich Apple nicht erinnern, auf welcher Seite der Suchergebnisse ich überhaupt war. IE7 verwenden. Sie benötigen eine Hash-Lösung. Siehe: Facebook.
Josh Stodola

Antworten:

106

Eine Antwort: Unload-Ereignisse führen unter anderem dazu, dass der Back / Forward-Cache ungültig wird .

Einige Browser speichern den aktuellen Status der gesamten Webseite im sogenannten "bfcache" oder "page cache". Auf diese Weise können sie die Seite beim Navigieren über die Schaltflächen Zurück und Vorwärts sehr schnell neu rendern und den Status des DOM und aller JavaScript-Variablen beibehalten. Wenn eine Seite jedoch Onunload-Ereignisse enthält, können diese Ereignisse die Seite möglicherweise in einen nicht funktionsfähigen Zustand versetzen. Daher wird die Seite nicht im bfcache gespeichert und muss neu geladen werden (kann jedoch aus dem Standardcache geladen werden) und erneut von Grund auf neu gerendert, einschließlich der Ausführung aller Onload-Handler. Wenn Sie über den bfcache zu einer Seite zurückkehren, bleibt das DOM in seinem vorherigen Zustand, ohne dass Onload-Handler ausgelöst werden müssen (da die Seite bereits geladen ist).

Beachten Sie, dass sich das Verhalten des bfcache in Bezug auf Cache-Control und andere HTTP-Header vom Standard-Browser-Cache unterscheidet. In vielen Fällen zwischenspeichern Browser eine Seite im bfcache, auch wenn sie sonst nicht im Standardcache gespeichert würden.

jQuery hängt automatisch ein Entladeereignis an das Fenster an. Wenn Sie also jQuery verwenden, wird Ihre Seite leider nicht im bfcache gespeichert, um das DOM zu erhalten und schnell vor- und zurückzuspulen. [Update: Dies wurde in jQuery 1.4 behoben, sodass es nur für den IE gilt.]

Meilen
quelle
3
du hast es total genagelt. Sowohl reddit als auch stackoverflow verwenden jquery, während basecamp und apple prototypejs verwenden. das erklärt so ziemlich alles.
Lubos Hasko
+1 interessant (aber nicht browserübergreifend) die Frage ist ganz anders als zu Beginn ...
BigBlondeViking
1
Es wird wahrscheinlich browserübergreifend sein, da ich es auch in meinem Internet Explorer reproduzieren kann. Ich bin mir sicher, dass jeder Webbrowser mit aktiviertem Javascript dieses Problem trotzdem lösen musste. Aber das ist wirklich ein Chaos. Wenn Sie darüber nachdenken, sollte der Zurück-Button immer die Leute auf die Seite bringen, die sie zuletzt mit allen DOM-Updates, dem Javascript-Status usw. gesehen haben. Entwickler sollten dies nicht durch Entladen von Ereignissen und Ereignissen unterbrechen In diesem Fall sollten Webbrowser nicht versuchen, das Problem zu beheben, indem sie bfcache überhaupt nicht verwenden. Das gesamte Entladeereignis ist ein großer Witz. Ich bin sicher, dass es zu 99% zum Patchen von Speicherlecks verwendet wird.
Lubos Hasko
1
Insbesondere leckt der IE-Speicher. :) Das jQuery-Entladeereignis behebt auch einen (völlig unabhängigen) Fehler in Firefox 2. Für andere Browser ist dies jedoch nicht erforderlich. dev.jquery.com/ticket/3015 Ich nehme an, ich habe von anderen Verwendungszwecken für Onunload gehört, wie dem Verfolgen ausgehender Klicks oder dem Speichern des Webapp-Status, aber ich hatte nie einen Grund, es selbst zu verwenden, und wenn Entwickler ihre erstellen möchten Websites, die langsamer und schmerzhafter für ihre Benutzer sind (ich hasse es, wenn das Zurücknavigieren zu reddit-Kommentarseiten den Status des reduzierten Kommentars zurücksetzt), das ist ihr Vorrecht.
Meilen
1
Das Entladeereignis ist nur für den IE angehängt, nicht für Firefox und Chrome. Die neueste Version von Safari bewahrt den Dom-Status, ohne dass der Entwickler etwas tun muss.
David
15

Ich habe versucht, Chrome dazu zu bringen, sich wie Safari zu verhalten, und die einzige Möglichkeit, die funktioniert, besteht darin, Cache-control: no-storedie Header festzulegen. Dies zwingt den Browser, die Seite erneut vom Server abzurufen, wenn der Benutzer die Zurück-Taste drückt. Nicht ideal, aber besser, als eine veraltete Seite anzuzeigen.

Nornagon
quelle
5
Dies ist die richtige Antwort auf die ursprüngliche Frage. Wenn Sie ein erneutes Laden des Servers auf der Zurück-Schaltfläche erzwingen möchten, verwenden Sie die Cache-Steuerung "Kein Speicher, kein Cache, muss erneut validiert werden". Chrome möchte No-Store und IE muss erneut validiert werden. Für andere Browser (und w3c) reicht kein Cache aus.
Woens
3

Facebook merkt sich den Seitenstatus, indem es die Hash-ID in der URL für Ajax-Anfragen ändert. Diese Änderungen werden im Browserverlauf aufgezeichnet. Wenn der Benutzer auf die Schaltfläche "Zurück" klickt, ändert sich der Hash auf den vorherigen Wert. Dann wird vorausgesetzt, dass Sie Javascript benötigen, um die Has-ID zu überwachen und zu reagieren, wenn sie vom Browser geändert wird. Andreas Blixt stellt ein Hash-Überwachungsskript zur Verfügung .

Josh Stodola
quelle
Ab heute stirbt es nicht, also kann ich sagen, was Facebook jetzt macht
Ravinder Payal
3

Dies hat nichts mit dem Hash-Symbol (#) zu tun.

Wenn Sie die HTTP-Header von Apple überprüfen würden, wird die Seite einfach zwischengespeichert.

Luca Matteis
quelle
Apple Beispiel ist schlecht, sie "speichern" nicht Seitenstatus, seine Annahme, dass das DOM es falsch erhalten wird
BigBlondeViking
2

Die Verwendung der URL-Hash- / Fragment-ID ist eine weit verbreitete Methode, um den Status in einer Webanwendung zu verknüpfen / zu speichern, die auf Ajax- und DOM-Updates basiert.

Schauen Sie sich das Really Simple History- Projekt für einige Ideen an. Es ist möglich, die URL auf Änderungen am Hash zu überwachen, und rsh führt dies unter Berücksichtigung der Browserunterschiede durch.

Peter
quelle
1

Für alle, die Probleme mit Railsund haben - Ihr Problem ist nicht bfcache (ich dachte es wäre) - es ist das turbolinksJuwel. Hier erfahren Sie, wie Sie es entfernen.

Hoffentlich sparen Sie dadurch etwas Zeit und schlagen Ihren Kopf gegen die Wand.

Yuval Karmi
quelle
0

Was Sie suchen, ist für eine Art von URL-Hash-Verwaltung. Das # in der URL ist nur für die Client-Seite.

Wenn Sie den Status der Rückseite mit JS ändern, aktualisieren Sie die Daten in der # der URL.

Außerdem fügen Sie eine Art von Abfrage hinzu, die überwacht, ob sich der Hash geändert hat, und den Status der Seite basierend auf den neuen Daten im Hash lädt.

Schau dir das an:

http://ajaxpatterns.org/Unique_URLs

BigBlondeViking
quelle
3
Dies hat nichts mit dem Hash-Symbol zu tun.
Luca Matteis
3
Sie liegen falsch, er sucht nach der gebräuchlichsten Methode, um den Seitenzustand in einer AJAX-Lösung beizubehalten.
BigBlondeViking