Po cofnięciu się do historii przeglądarki Firefox JavaScript nie będzie działać

84

Kiedy używam przycisku Wstecz w przeglądarce Firefox, aby przejść do poprzednio odwiedzanej strony, skrypty na tej stronie nie będą działać ponownie .

Czy jest jakieś rozwiązanie / obejście umożliwiające ponowne wykonanie skryptów podczas przeglądania strony po raz drugi?

Pamiętaj, że testowałem te same strony w Google Chrome i Internet Explorer i działają zgodnie z przeznaczeniem.


Oto pliki i kroki, które wykonałem, aby przetestować problem:

(przejdź do 0.html, kliknij, aby przejść do 1.html, przycisk Wstecz)

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
źródło

Odpowiedzi:

93

Ustaw pustą funkcję do wywołania w oknie .onunload:

window.onunload = function(){}; 

na przykład

<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>

Źródło: http://www.firefoxanswer.com/firefox/672-firefoxanswer.html (wersja zarchiwizowana)

John Baber-Lucero
źródło
2
Dziękuję, działa. Jakieś wskazówki na temat tego, co robi domyślna procedura obsługi onunload? (np. czy nadpisuję tutaj jakieś domyślne zachowanie?)
Patonza
Ok, dzięki, zbadam sprawę.
Jeszcze
ktoś wie, dlaczego FireFox tego potrzebuje, a inne przeglądarki nie?
Pim Jager
7
Nie nadpisujesz niczego, to po prostu zapobiega buforowaniu strony przez przeglądarkę Firefox w pamięci podręcznej wstecznej do przodu (bfcache). developer.mozilla.org/en/DOM/window.onunload developer.mozilla.org/En/Using_Firefox_1.5_caching
Chris Haas
1
Chociaż powinno to zepsuć bfcache, niestety wydaje się, że nadal pamięta poprzednią stronę - w szczególności, adresy URL ramek iframe, które zostały załadowane, są ładowane ponownie, gdy wracasz, i jeśli wygenerowana zawartość musiała zostać umieszczona w ramce, nie wydaje się, aby istniała przeglądarka sposób na odświeżenie tego na nowo.
NoBugs
76

Kiedy używam przycisku Wstecz w przeglądarce Firefox, aby przejść do poprzednio odwiedzanej strony, skrypty na tej stronie nie będą działać ponownie.

Zgadza się i to dobrze.

Kiedy trafisz na łącze w przeglądarce Firefox (oraz Safari i Opera), nie niszczy to natychmiast twojej strony, aby przejść do następnej. Utrzymuje stronę w stanie nienaruszonym, jedynie ukrywając ją przed widokiem. Jeśli naciśniesz przycisk Wstecz, ponownie wyświetli się stara strona bez konieczności ponownego ładowania dokumentu; jest to znacznie szybsze, co skutkuje płynniejszym przejściem strony wstecz / dalej dla użytkownika.

Ta funkcja nosi nazwę bfcache .

Wszelkie treści dodane do strony podczas poprzedniego ładowania użytkownika i korzystania z niej będą nadal dostępne. Wszystkie programy obsługi zdarzeń dołączone do elementów strony będą nadal dołączone. Wszelkie ustawione limity czasu / interwały będą nadal aktywne. Rzadko więc istnieje powód, dla którego musisz wiedzieć, że zostałeś ukryty i ponownie pokazany. Błędem byłoby onloadponowne wywołanie lub wbudowany kod skryptu, ponieważ każde powiązanie i generowanie treści wykonane w tej funkcji byłoby wykonywane po raz drugi na tej samej zawartości, co mogłoby mieć katastrofalne skutki. (np. document.writew skrypcie wbudowanym całkowicie zniszczyłoby stronę).

Powodem, dla którego pisanie do window.onunloadma wpływ, jest to, że przeglądarki, które implementują bfcache, zdecydowały, że - ze względu na zgodność ze stronami, które naprawdę muszą wiedzieć, kiedy są odrzucane - każda strona, która deklaruje zainteresowanie wiedzą, kiedy onunloadwystąpi, spowoduje, że bfcache być niepełnosprawnym. Ta strona zostanie załadowana na nowo, gdy wrócisz do niej, zamiast pobierana z bfcache.

Więc jeśli ustawisz window.onunload= function() {};, to, co faktycznie robisz, to celowe niszczenie bfcache. Spowoduje to spowolnienie nawigacji na stronach i nie powinno być używane z wyjątkiem ostateczności.

Jeśli chcesz wiedzieć, kiedy użytkownik opuszcza lub wraca na twoją stronę, bez naruszania bfcache, możesz zamiast tego przechwycić zdarzenia onpageshowi onpagehide:

window.onload=window.onpageshow= function() {
    alert('Hello!');
};
bobince
źródło
3
Mój problem polega na tym, że bfcache nie buforuje CAŁEJ strony, więc muszę ponownie uruchomić js, aby odbudować utraconą zawartość. Więc rzucanie całej strony może być w porządku. W każdym razie nie używam zdarzenia window.onload, używam zdarzenia document.ready jQuery. Czy znasz sposób, aby nadal móc korzystać z document.ready i uniknąć tego problemu?
Patonza
bfcache powinien generalnie zwracać całą stronę w takiej postaci, w jakiej została opuszczona. Czego brakuje po powrocie z poprzedniej strony? (przypadek testowy?) document.readybędzie działać zasadniczo w taki sam sposób, jak window.onload(dla niektórych przeglądarek i tak są to to samo zdarzenie).
bobince
14
To NIE jest dobra rzecz, ponieważ nie uruchamia on ponownie javascript, biorąc pod uwagę, że jest buforowany ... ale tak naprawdę NIE Buforuje zmian, które wcześniej wprowadził javascript. Jeśli javascript zanika w elemencie podczas wczytywania strony, nie zanika go ponownie podczas odwiedzania w historii ... ale CZY ROZPOCZYNA go ponownie z kryciem 0, cofając to, co zrobił javascript! To musi być WSZYSTKO ALBO NIC. Musisz zbuforować cały stan strony po uruchomieniu javascript, jeśli chcesz zaprezentować ją w pamięci podręcznej bez ponownego uruchamiania javascript!
Jimbo Jonny
1
@Jimbo: Przypadek testowy, proszę. bfcache ma na celu (iw każdym przypadku, jaki kiedykolwiek widziałem, zachowuje) zachowanie dokładnego stanu DOM-a przed ukrywaniem / pokazywaniem. Element, który został wyblakły, pozostanie nieprzezroczysty po powrocie do strony, chyba że uruchomi się inny skrypt, aby go ponownie ukryć.
bobince
1
@bobince - Stwórz element z plikiem CSS, ustawiając krycie na zero, a następnie użyj jQuery, aby pojawił się w dokumencie. Po cofnięciu się do historii ponownie zastosuje arkusz stylów CSS (zero) bez zachowania krycia: 1, które JS dodał do atrybutu stylu podczas jego zanikania. Przy pierwszej wizycie na stronie element zanika od zera do 1. Przejdź do innej strony i wróć, a po prostu będzie w pełni przezroczysty.
Jimbo Jonny
23

Możesz sprawdzić persistedwłaściwości pageshowwydarzenia. Przy pierwszym wczytywaniu strony ma wartość false. Kiedy strona jest ładowana z pamięci podręcznej, ustawiana jest na true.

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

Z jakiegoś powodu jQuery nie ma tej właściwości w zdarzeniu. Można go jednak znaleźć z oryginalnego wydarzenia.

$(window).bind("pageshow", function(event) {
    if (event.originalEvent.persisted) {
        alert("From bfcache");
    }
});
Mika Tuupola
źródło
Dziękujemy za udostępnienie wersji javascript i jquery! Na końcu przegapiłeś ścisły nawias (to nie jest jęk!). Zaznaczę również, ze względu na innych, że raport IE i Chrome .persisted jest zawsze fałszywy, niezależnie od tego.
Magnus Smith
Jak zauważył Magnus, nie działało to dla mnie w Chrome, dopóki nie usunąłem instrukcji if.
Justin
To działało dla mnie w Chrome 58.0.3029.110 (64-bitowy) i FF 53.0.2 (64-bitowy) bez żadnych zmian.
kmoser
1

Połącz w zdarzeniu „onunload”, które nic nie robi:

<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
źródło
Nie jestem pewien, oddałem głos, wygląda na to, że ktoś właśnie przegłosował każdą odpowiedź na to pytanie ...
Patonza
do odpowiedzi należy dodać, że dodanie zdarzenia onunload do strony w rzeczywistości całkowicie wyłączy buforowanie strony. Nie powoduje to po prostu ponownego uruchomienia JS, ale także spowoduje wzrost obciążenia serwera. To naprawdę nie jest sugestia, którą należy lekceważyć, należy to dokładnie rozważyć.
dreagan
@dreagan, to wyłącza bfcache, ale niekoniecznie bufor HTTP. Pamięć podręczna HTTP ma zupełnie inny zestaw reguł. Jeśli wrzucisz tam sen po stronie serwera, powinieneś to zauważyć podczas klikania wstecz. Mozilla mówi o tym w swoim trzecim pytaniu w FAQ dla BFCache .
Chris Haas
Mówiłem o BFcache, powinienem to określić. Nie oznacza to, że powinieneś udzielać takiej sugestii bez powiadamiania PO o konsekwencjach. Alternatywą byłoby użycie zdarzenia onpopstate w celu ponownego uruchomienia kodu JavaScript.
dreagan
Nadal nie wiem, czy rozumiem. Dlaczego „obciążenie serwera wzrosło”, jeśli lokalny plik bfcache klienta zostałby ominięty? Tak, DOM będzie musiał zostać przebudowany, ale HTML powinien być częścią pamięci podręcznej HTTP klienta. Tak, dodatkowe zasoby będą musiały zostać ponownie załadowane, ale powinny one być również częścią pamięci podręcznej HTTP klienta. Jeśli chodzi o onpopstatepytanie, kiedy to pytanie zadano prawie pięć lat temu, to wydarzenie było wciąż stosunkowo nowe, a obsługa przeglądarek była bardzo niespójna
Chris Haas
1

O ile wiem, Firefox nie uruchamia onLoadzdarzenia z tyłu.

Powinien wyzwalać onFocus zamiast na podstawie tego linku tutaj .

systempuntoout
źródło
Przetestowałem to i windows.onfocus rzeczywiście został wywołany, nawet bez ustawienia pustego modułu obsługi window.onunload. Ustawienie onunload jest nieco przyjemniejszym obejściem, ale .onfocus też powinno wystarczyć. Dzięki :)
Patonza,
1

Prostym sposobem spowodowania, aby strona wykonywała JavaScript, gdy użytkownik przechodzi z powrotem do niej przy użyciu historii przeglądarki, jest zdarzenie OnPopState. Używamy tego do wstrzymywania i ponownego odtwarzania wideo na naszej stronie głównej ( https://fynydd.com ).

window.onpopstate = function() {

    // Do stuff here...
};
Michael A.
źródło
0

w niektórych przypadkach, takich jak operacje AJAX, można użyć nasłuchiwania zmian adresu URL

$(window).on('hashchange', function() {
        ....
});
Pogromca
źródło