Czy po kliknięciu przycisku Wstecz występuje zdarzenie obciążenia w różnych przeglądarkach?


185

We wszystkich głównych przeglądarkach (oprócz IE) onloadzdarzenie JavaScript nie jest uruchamiane, gdy strona ładuje się w wyniku operacji przycisku Wstecz - uruchamia się tylko przy pierwszym załadowaniu strony.

Czy ktoś może wskazać mi przykładowy kod przeglądarki (Firefox, Opera, Safari, IE,…), który rozwiązuje ten problem? Znam pageshowwydarzenie Firefoksa, ale niestety ani Opera, ani Safari nie implementują tego.


6
Nie stanowi to problemu - umożliwia szybkie ładowanie strony internetowej, gdy użytkownik naciśnie przycisk Wstecz. Zobacz moją odpowiedź poniżej, aby uzyskać szczegółowe informacje. Sugerowane tutaj obejścia sprawiają, że strona internetowa jest bardziej irytująca dla użytkownika, ponieważ nawigacja do tyłu / do przodu jest wolniejsza.
Nickolay,

2
@romkyns: Twój komentarz nie jest związany z tym pytaniem. Gdy przeglądarki nie przywracają stanu JS / DOM, uruchamiają zdarzenie ładowania.
Nickolay

Rozwiązany tutaj przycisk powrotu historii iOS 5+ stackoverflow.com/a/12652160/1090395
Mladen Janjetovic

Odpowiedzi:


117

Ludzie, odkryłem, że JQuery ma tylko jeden efekt: strona jest ładowana ponownie po naciśnięciu przycisku Wstecz. Nie ma to nic wspólnego z „ gotowym ”.

Jak to działa? Cóż, JQuery dodaje detektor zdarzeń onunload .

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

Domyślnie nic nie robi. Ale jakoś to wydaje się wyzwalać przeładowanie w Safari, Operze i Mozilli - bez względu na to, co zawiera moduł obsługi zdarzeń.

[ edit (Nickolay) : oto dlaczego tak działa: webkit.org , developer.mozilla.org . Przeczytaj te artykuły (lub moje streszczenie w osobnej odpowiedzi poniżej) i zastanów się, czy naprawdę musisz to zrobić i spowolnić ładowanie strony dla użytkowników.]

Nie możesz w to uwierzyć? Spróbuj tego:

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

Podobne wyniki zobaczysz podczas korzystania z JQuery.

Możesz porównać do tego bez obciążenia

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

1
Bardzo fajnie .. chociaż jest to nieudokumentowana funkcja / błąd i może po prostu przestać działać w przyszłych wersjach przeglądarki, ale nadal jest interesująca.
Wadih M.

3
Działa to również (nie zapomnij o części onunload = "", w przeciwnym razie nie zadziała na ff3): <body onload = "alert ('onload');" onunload = "">
Wadih M.

3
Wynika to z faktu, że przeglądarka zakłada, że ​​strona jest nieuleczalna, jeśli ma moduł onunloadobsługi (strona już wszystko zniszczyła; po co ją buforować?).
Casey Chu,

14
Odpowiedź wydaje się nie działać w nowoczesnych przeglądarkach - sprawdzonych w najnowszym Chrome i Operze
Andrew

10
nie działa w safari na iPadzie ... proszę odznacz to jako odpowiedź
xus

74

Niektóre nowoczesne przeglądarki (Firefox, Safari i Opera, ale nie Chrome) obsługują specjalną pamięć podręczną „wstecz / do przodu” (nazywam ją bfcache, która jest terminem wymyślonym przez Mozillę), zaangażowaną, gdy użytkownik nawiguje wstecz. W przeciwieństwie do zwykłej pamięci podręcznej (HTTP), przechwytuje pełny stan strony (w tym stan JS, DOM). Pozwala to na szybsze ładowanie strony dokładnie tak, jak użytkownik ją opuścił.

loadWydarzenie nie ma ognia, gdy strona jest ładowany z tego bfcache. Na przykład, jeśli utworzyłeś swój interfejs w module obsługi „load”, a zdarzenie „load” zostało uruchomione raz przy pierwszym ładowaniu, a po raz drugi, gdy strona została ponownie załadowana z bfcache, strona skończyłaby się zduplikowane elementy interfejsu użytkownika.

Z tego powodu dodanie modułu obsługi „unload” powoduje, że strona nie jest przechowywana w bfcache (co spowalnia powrót do poprzedniej strony) - moduł obsługi unload może wykonywać zadania czyszczenia, które mogą pozostawić stronę w stanie niemożliwym do wykonania.

W przypadku stron, które muszą wiedzieć, kiedy są nawigowane do / z powrotem, Firefox 1.5+ i wersja Safari z poprawką błędu 28758 obsługują specjalne zdarzenia o nazwie „pagehow” i „pagehide”.

Bibliografia:


To bardzo fajnie. Jestem obecnie w sytuacji, gdy moje manipulacje domem nie wydają się być zapisane w bfcache. Czy są jakieś sytuacje, w których można się tego spodziewać?
Benson

1
@Benson: możliwe powody, dla których Firefox nie zapisuje twojej strony w bfcache, są wymienione na stronie dev.mo, do której linkowałem. Nie sądzę, aby możliwe było zapisanie strony w bfcache, ale nie można zapisać niektórych stanów DOM.
Nickolay

Nickolay, dostaję twoją niechęć do wymuszenia przeładowania i cofnięcia dobrej pracy wykonanej przez bfcache, ale czy istnieje inny sposób aktualizacji domeny strony w bfcache? Rozważmy na przykład sytuację, w której przechodzę ze strony, która zawiera listę wiadomości do jednej z nich, a kiedy wracam, chcę zmienić wskaźnik odczytu / nieprzeczytanego. Jak można to zrobić bez ponownego ładowania strony?
Greg

@Greg: masz na myśli jako programistę kontrolującego stronę? Uruchom żądanie ajax od nasłuchiwania „pagehow”.
Nickolay

Wszelkie pomysły na temat korzystania z jQuery ORAZ uzyskać szybką obsługę bfcache?
Alex Black,

31

Wystąpił problem, który nie był wykonywany przez mój plik js, gdy użytkownik kliknął przycisk Wstecz lub Dalej. Najpierw postanowiłem zatrzymać buforowanie przeglądarki, ale nie wyglądało to na problem. Mój skrypt javascript został skonfigurowany do działania po załadowaniu wszystkich bibliotek itp. Sprawdziłem je za pomocą zdarzenia readyStateChange.

Po kilku testach dowiedziałem się, że element readyState elementu na stronie, na której kliknięto Wstecz, nie jest „ładowany”, ale „zakończony”. Dodanie || element.readyState == 'complete'do mojego warunkowego stwierdzenia rozwiązało moje problemy.

Pomyślałem, że podzielę się swoimi odkryciami, mam nadzieję, że pomogą komuś innemu.

Edytuj dla kompletności

Mój kod wyglądał następująco:

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

W powyższym przykładzie kodu zmienną skryptu był nowo utworzony element skryptu, który został dodany do modelu DOM.


7
Gdzie to dodałeś? I w jaki sposób udało Ci się wystrzelić po tym, jak użytkownik odpowiedział? Pokaż nam kod!
Keerigan,

Co masz na myśli mówiąc „moje warunkowe stwierdzenie”?
Phillip Senn,

1
@Phillip Instrukcja warunkowa jest instrukcją if.
Brian Heese,

22

OK, oto ostateczne rozwiązanie oparte na wstępnym rozwiązaniu ckramera i przykładzie palehorse, które działa we wszystkich przeglądarkach, w tym w Operze. Jeśli ustawisz history.navigationMode na „zgodny”, funkcja gotowości jQuery uruchomi się na operacjach przycisku Wstecz w Operze, a także w innych głównych przeglądarkach.

Ta strona zawiera więcej informacji .

Przykład:

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

Przetestowałem to w Operze 9.5, IE7, FF3 i Safari i działa we wszystkich.


2
Oczywiście minęło trochę czasu (około 5,5 roku), ale warto zauważyć, że Twój link nie działa.
Jeff

2
To rozwiązanie nie działa dla mnie. Mam ten problem w najnowszej przeglądarce Firefox (45.0.1)
Armin

6

Nie udało mi się uruchomić powyższych przykładów. Po prostu chciałem uruchomić odświeżanie niektórych zmodyfikowanych obszarów div, gdy wracam na stronę za pomocą przycisku Wstecz. Sztuczka, której użyłem, polegała na ustawieniu ukrytego pola wejściowego (zwanego „brudnym bitem”) na 1, gdy tylko obszary div zmieniły się z oryginału. Ukryte pole wejściowe faktycznie zachowuje swoją wartość po kliknięciu, więc onload mogę sprawdzić ten bit. Jeśli jest ustawiony, odświeżam stronę (lub po prostu odświeżam div). Jednak przy oryginalnym ładowaniu bit nie jest ustawiony, więc nie tracę czasu na ładowanie strony dwukrotnie.

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

I zadziałałby poprawnie, gdy kliknę przycisk Wstecz.


3
Chociaż nie działa to w Firefoksie, myślę, że jest to sprytny sposób radzenia sobie z sytuacją w IE / Chrome, w której utrzymanie ukrytego pola jest bardzo przydatne. Użyłem twojej sztuczki, a także wydarzenia „pagehow”, więc obejmuję wszystkie główne przeglądarki.
Magnus Smith,

Jaka przeglądarka nie działa w taki sposób?
Justin

4

Jeśli dobrze pamiętam, dodanie zdarzenia unload () oznacza, że ​​strony nie można buforować (w pamięci podręcznej do przodu / do tyłu) - ponieważ jej stan zmienia się / może ulec zmianie, gdy użytkownik opuści stronę. Tak więc - nie jest bezpiecznie przywracać stanu ostatniej sekundy strony podczas powrotu do niej poprzez nawigację po obiekcie historii.


4

Myślałem, że będzie to dotyczyło „onunload”, a nie ładowania strony, ponieważ czy nie mówimy o uruchomieniu zdarzenia po naciśnięciu „Back”? $ document.ready () dotyczy zdarzeń pożądanych przy ładowaniu strony, bez względu na to, jak dojdziesz do tej strony (tj. przekierowanie, otwarcie przeglądarki bezpośrednio na adres URL itp.), a nie kliknięcie „Wstecz”, chyba że mówisz o tym, co wystrzelić na poprzedniej stronie, gdy zostanie ponownie załadowana. I nie jestem pewien, czy strona nie jest buforowana, ponieważ zauważyłem, że JavaScript nadal jest dostępny, nawet jeśli zawiera on $ document.ready (). Musieliśmy nacisnąć Ctrl + F5 podczas edycji naszych skryptów, które mają to wydarzenie, za każdym razem, gdy je poprawimy i chcemy przetestować wyniki na naszych stronach.

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

jest to, czego chcesz dla zdarzenia onunload po naciśnięciu „Wstecz” i rozładowaniu bieżącej strony, a także uruchamiałby się, gdy użytkownik zamknie okno przeglądarki. To brzmiało bardziej jak to, co było pożądane, nawet jeśli mam przewagę liczebną odpowiedzi $ document.ready (). Zasadniczo różnica polega na tym, że zdarzenie jest uruchamiane na bieżącej stronie podczas jej zamykania lub na tym, które ładuje się po kliknięciu „Wstecz” podczas ładowania. Testowane w IE 7 w porządku, nie mogą mówić w przypadku innych przeglądarek, ponieważ nie są dozwolone tam, gdzie jesteśmy. Ale może to być inna opcja.


4

Mogę potwierdzić ckramer, że gotowe zdarzenie jQuery działa w IE i FireFox. Oto próbka:

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

4

dla osób, które nie chcą korzystać z całej biblioteki jquery, wyodrębniłem implementację w osobnym kodzie. Ma tylko 0,4 KB.

Kod wraz z niemieckim samouczkiem można znaleźć na tej wiki: http://www.easy-coding.de/wiki/html-ajax-und-co/onload-event-cross-browser-kompatibler-domcontentloaded.html


1
Samotny link jest uważany za kiepską odpowiedź (patrz często zadawane pytania ), ponieważ sam w sobie jest bez znaczenia, a zasoby docelowe nie są gwarantowane w przyszłości . Lepiej byłoby zawrzeć tutaj istotne części odpowiedzi i podać odnośnik.
j0k

3

Gotowe wydarzenie jQuery zostało stworzone tylko dla tego rodzaju problemu. Możesz zagłębić się w implementację, aby zobaczyć, co się dzieje pod przykryciem.


6
Długo później readywydaje się , że nie jest uruchamiany w Firefoksie, gdy używasz przycisku Wstecz. Zobacz także odpowiedź Nickolay .
Arjan

2

Bill, odważę się odpowiedzieć na twoje pytanie, jednak nie jestem w 100% pewien swoich przypuszczeń. Myślę, że przeglądarki inne niż IE, gdy zabiorą użytkownika na stronę w historii, nie tylko załadują stronę i jej zasoby z pamięci podręcznej, ale także przywrócą dla niej cały stan DOM (sesja odczytu). IE nie wykonuje przywracania DOM (lub nie dzierżawi tego), dlatego zdarzenie onload wydaje się konieczne do prawidłowej ponownej inicjalizacji strony.


2

Wypróbowałem rozwiązanie od Billa za pomocą $ (dokumentu) .ready ... ale na początku nie zadziałało. Odkryłem, że jeśli skrypt zostanie umieszczony za sekcją HTML, to nie będzie działać. Jeśli jest to sekcja główna, będzie działać, ale tylko w IE. Skrypt nie działa w przeglądarce Firefox.


1

OK, próbowałem tego i działa w Firefox 3, Safari 3.1.1 i IE7, ale nie w Operze 9.52.
Jeśli użyjesz przykładu pokazanego poniżej (na podstawie przykładu palehorse), pojawi się okienko z ostrzeżeniem, gdy strona zostanie załadowana po raz pierwszy. Ale jeśli przejdziesz do innego adresu URL, a następnie wciśniesz przycisk Wstecz, aby wrócić do tej strony, w Operze nie pojawi się wyskakujące okienko z ostrzeżeniem (ale w innych przeglądarkach).

W każdym razie myślę, że na razie jest wystarczająco blisko. Dziękuję wszystkim!

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

1

Zdarzenie wyładowania nie działa poprawnie w IE 9. Wypróbowałem to ze zdarzeniem load (onload ()), działa dobrze w IE 9 i FF5 .

Przykład:

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

0

Użyłem szablonu HTML. W pliku custom.js tego szablonu była taka funkcja:

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

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

    });

Ale ta funkcja nie działała, gdy wracam do poprzedniej strony.

Próbowałem tego i zadziałało:

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

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

Teraz mam 2 funkcje „gotowe”, ale nie daje to żadnego błędu, a strona działa bardzo dobrze.

Niemniej jednak muszę zadeklarować, że przetestował na Windows 10 - Opera v53 i Edge v42, ale nie ma innych przeglądarek. Pamiętaj o tym ...

Uwaga: wersja jquery to 3.3.1, a wersja migracji to 3.0.0

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.