Ajax, przycisk Wstecz i aktualizacje DOM

113

Jeśli javascript modyfikuje DOM na stronie A, użytkownik przechodzi do strony B, a następnie naciska przycisk Wstecz, aby wrócić do strony A. Wszystkie modyfikacje DOM strony A zostają utracone, a użytkownikowi zostaje przedstawiona wersja, która została pierwotnie pobrana z serwera.

Działa w ten sposób na stackoverflow, reddit i wielu innych popularnych witrynach. (spróbuj dodać komentarz testowy do tego pytania, a następnie przejdź do innej strony i naciśnij przycisk Wstecz, aby wrócić - Twój komentarz zniknie)

Ma to sens, ale niektóre witryny (apple.com, basecamphq.com itp.) W jakiś sposób wymuszają na przeglądarce udostępnianie użytkownikowi najnowszego stanu strony. (przejdź do http://www.apple.com/ca/search/?q=ipod , kliknij link do pobrania u góry, a następnie kliknij przycisk Wstecz - wszystkie aktualizacje DOM zostaną zachowane)

skąd bierze się niespójność?

lubos hasko
źródło
Co ciekawe, Apple pamięta stan bez modyfikowania skrótu… hmmm
James
Wygląda na to, że Apple manipuluje buforowaniem odpowiedzi
BigBlondeViking
Jak już sugerowali inni, nie jest to coś związanego z javascript lub ajax. Powinieneś usunąć te tagi, aby uzyskać prawidłowe odpowiedzi.
BYK
Przykład Apple jest kiepski. Jeśli zawrzesz obszar wyszukiwania [np. Produkty], kliknij link, a następnie naciśnij przycisk Wstecz, DOM nie zostanie zachowany. szukasz rozwiązania Hash, które wielu sugerowało.
BigBlondeViking
Kiedy wciskam przycisk Wstecz, Apple w ogóle nie pamięta, na której stronie wyników wyszukiwania byłem. Korzystanie z IE7. Potrzebujesz rozwiązania skrótu. Zobacz: Facebook.
Josh Stodola

Odpowiedzi:

106

Jedna odpowiedź: między innymi zdarzenia rozładowania powodują unieważnienie pamięci podręcznej wstecz / dalej .

Niektóre przeglądarki przechowują aktualny stan całej strony internetowej w tzw. „Bfcache” lub „page cache”. Dzięki temu mogą bardzo szybko ponownie wyrenderować stronę podczas nawigacji za pomocą przycisków Wstecz i Dalej oraz zachować stan DOM i wszystkich zmiennych JavaScript. Jednak gdy strona zawiera zdarzenia onunload, zdarzenia te mogą potencjalnie spowodować, że strona przejdzie w stan niefunkcjonalny, więc strona nie jest przechowywana w bfcache i musi zostać ponownie załadowana (ale może zostać załadowana ze standardowej pamięci podręcznej) i ponownie renderowane od podstaw, w tym uruchamianie wszystkich programów obsługi ładowania. Podczas powrotu do strony przez bfcache, DOM jest utrzymywany w swoim poprzednim stanie, bez konieczności uruchamiania programów obsługi ładowania (ponieważ strona jest już załadowana).

Należy zauważyć, że zachowanie bfcache różni się od standardowej pamięci podręcznej przeglądarki w odniesieniu do Cache-Control i innych nagłówków HTTP. W wielu przypadkach przeglądarki będą buforować stronę w bfcache, nawet jeśli w innym przypadku nie zapisałyby jej w standardowej pamięci podręcznej.

jQuery automatycznie dołącza zdarzenie unload do okna, więc niestety użycie jQuery zdyskwalifikuje twoją stronę z bfcache w celu zachowania DOM i szybkiego przewijania do tyłu / do przodu. [Aktualizacja: zostało to naprawione w jQuery 1.4, więc dotyczy tylko IE]

Miles
źródło
3
całkowicie to załatwiłeś. zarówno reddit, jak i stackoverflow używają jquery, podczas gdy basecamp i apple używają prototypejs. to właściwie wszystko wyjaśnia.
lubos hasko
+1 interesujący (choć nie w wielu przeglądarkach) pytanie jest znacznie inne niż na początku ...
BigBlondeViking
1
prawdopodobnie będzie to cross-browser, ponieważ mogę odtworzyć go również w moim Internet Explorerze. Jestem pewien, że każda przeglądarka internetowa z włączoną obsługą JavaScript i tak miała do czynienia z tym problemem. ale to naprawdę bałagan, kiedy się nad tym zastanowić, przycisk Wstecz powinien zawsze kierować ludzi na stronę, którą widzieli jako ostatnią ze wszystkimi aktualizacjami DOM, stanem javascript itp. programiści nie powinni tego przerywać, robiąc coś w zdarzeniu unload i jeśli tak, przeglądarki internetowe nie powinny próbować naprawiać problemu, nie używając w ogóle bfcache. całe zdarzenie rozładunku to jeden wielki żart. Jestem pewien, że 99% czasu służy do naprawiania wycieków pamięci.
lubos hasko
1
W szczególności wycieki pamięci IE. :) Zdarzenie wyładowania jQuery również naprawia (zupełnie niezwiązany) błąd w Firefoksie 2. Ale jest to niepotrzebne dla innych przeglądarek. dev.jquery.com/ticket/3015 Przypuszczam, że słyszałem o innych zastosowaniach onunload, takich jak śledzenie kliknięć wychodzących lub zapisywanie stanu aplikacji internetowej, ale nigdy nie miałem powodu, aby go używać, a jeśli programiści chcą, aby ich witryny wolniejsze i bardziej bolesne dla ich użytkowników (nienawidzę tego, jak powrót do stron z komentarzami reddit resetuje stan zwinięcia komentarzy), to ich przywilej.
Miles
1
Zdarzenie unload jest dołączane tylko dla IE, a nie dla Firefoxa i Chrome. Najnowsza wersja safari zachowuje stan dom bez konieczności wykonywania jakichkolwiek czynności przez programistę.
David
15

Próbowałem sprawić, aby Chrome zachowywał się tak, jak robi to Safari, i jedynym sposobem, w jaki się przekonałem, jest ustawienie Cache-control: no-storew nagłówkach. Zmusza to przeglądarkę do ponownego pobrania strony z serwera, gdy użytkownik naciśnie przycisk Wstecz. Nie jest to idealne rozwiązanie, ale lepsze niż wyświetlanie nieaktualnej strony.

nornagon
źródło
5
To jest poprawna odpowiedź na pierwotne pytanie. Jeśli chcesz wymusić ponowne załadowanie serwera za pomocą przycisku Wstecz, użyj kontroli pamięci podręcznej „no-store, no-cache, must-revalidate”. Chrome nie chce przechowywać, a IE chce ponownie zweryfikować. W przypadku innych przeglądarek (i w3c) wystarczy no-cache.
woens
3

Facebook zapamiętuje stan strony, modyfikując identyfikator skrótu w adresie URL dla żądań Ajax. Te zmiany są zapisywane w historii przeglądarki, więc gdy użytkownik kliknie przycisk Wstecz, skrót zmieni się na taki, jaki był wcześniej. Zakłada się więc, że będziesz potrzebować JavaScript do monitorowania identyfikatora has i reagowania, gdy zostanie zmieniony przez przeglądarkę. Andreas Blixt ma dostępny skrypt monitorowania skrótu .

Josh Stodola
źródło
na dzień dzisiejszy nie umiera, więc możesz mi powiedzieć, co robi teraz Facebook
Ravinder Payal
3

Nie ma to nic wspólnego z symbolem krzyżyka (#).

Jeśli chcesz sprawdzić nagłówki HTTP firmy Apple, po prostu buforujesz stronę.

Luca Matteis
źródło
Przykład Apple jest kiepski, nie „zapisują” stanu strony, jego założenie DOM jest zachowane.
BigBlondeViking
2

Używanie skrótu / identyfikatora fragmentu adresu URL jest dość powszechnym sposobem przechwytywania / zapamiętywania stanu w aplikacji internetowej, która opiera się na aktualizacjach Ajax i DOM.

Sprawdź projekt Really Simple History , aby znaleźć kilka pomysłów. Możliwe jest monitorowanie adresu URL pod kątem zmian w hashu, a rsh robi to, biorąc pod uwagę różnice między przeglądarkami.

Piotr
źródło
1

Dla każdego, kto ma problemy z Railsi tym - twoim problemem nie jest bfcache (myślałem, że tak) - to turbolinksklejnot. Oto jak go usunąć.

Miejmy nadzieję, że zaoszczędzi ci to trochę czasu i uderzy głową o ścianę.

Yuval Karmi
źródło
0

To, czego szukasz, dotyczy pewnego rodzaju zarządzania skrótami adresów URL. # W adresie URL jest tylko po stronie klienta.

Kiedy zmieniasz stan tyłu za pomocą JS, aktualizujesz dane w # adresu URL.

Dodajesz również rodzaj odpytywania, który monitoruje, czy hash się zmienił, i ładuje stan strony na podstawie nowych danych w hashu.

Spójrz na to:

http://ajaxpatterns.org/Unique_URLs

BigBlondeViking
źródło
3
nie ma to nic wspólnego z symbolem krzyżyka.
Luca Matteis
3
Mylisz się, on szuka najczęstszego sposobu zachowania stanu strony w rozwiązaniu AJAX.
BigBlondeViking