Esiste un evento di caricamento cross-browser quando si fa clic sul pulsante Indietro?

StackOverflow https://stackoverflow.com/questions/158319

  •  03-07-2019
  •  | 
  •  

Domanda

Per tutti i principali browser (tranne IE), l'evento JavaScript onload non si attiva quando la pagina viene caricata a seguito di un'operazione con il pulsante Indietro, ma si attiva solo quando la pagina viene caricata per la prima volta.

Qualcuno può indicarmi un codice cross-browser di esempio (Firefox, Opera, Safari, IE, ...) che risolve questo problema? Conosco l'evento pageshow di Firefox, ma sfortunatamente né Opera né Safari lo implementano.

È stato utile?

Soluzione

Ragazzi, ho scoperto che JQuery ha un solo effetto: la pagina viene ricaricata quando si preme il pulsante Indietro. Questo non ha nulla a che fare con " pronto " ;.

Come funziona? Bene, JQuery aggiunge un onunload listener di eventi.

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

Per impostazione predefinita, non fa nulla. Ma in qualche modo questo sembra innescare un ricaricamento in Safari, Opera e Mozilla, indipendentemente dal contenuto del gestore eventi.

[ edit (Nickolay) : ecco perché funziona in questo modo: webkit.org , developer.mozilla. org . Leggi quegli articoli (o il mio sommario in una risposta separata di seguito) e considera se davvero devi fare questo e rendere il caricamento della tua pagina più lento per i tuoi utenti.]

Non ci credi? Prova questo:

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

Vedrai risultati simili usando JQuery.

Potresti voler comparare a questo senza onunload

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

Altri suggerimenti

Alcuni browser moderni (Firefox, Safari e Opera, ma non Chrome) supportano lo speciale "indietro / avanti" cache (lo chiamerò bfcache, che è un termine inventato da Mozilla), coinvolto quando l'utente naviga indietro. A differenza della normale cache (HTTP), acquisisce lo stato completo della pagina (incluso lo stato di JS, DOM). Ciò consente di ricaricare la pagina più velocemente e esattamente come l'utente l'ha lasciata.

L'evento load non dovrebbe attivarsi quando la pagina viene caricata da questo bfcache. Ad esempio, se hai creato l'interfaccia utente in " carica " gestore e il "caricamento" l'evento è stato generato una volta sul caricamento iniziale e la seconda volta in cui la pagina è stata ricaricata dalla bfcache, la pagina sarebbe finita con elementi dell'interfaccia utente duplicati.

Questo è anche il motivo per cui l'aggiunta di " unload " il gestore interrompe l'archiviazione della pagina in bfcache (rendendo così più lento il ritorno a) - il gestore di scarico potrebbe eseguire attività di pulizia, che potrebbero lasciare la pagina in uno stato non realizzabile.

Per le pagine che devono sapere quando vengono spostate via / indietro, Firefox 1.5+ e la versione di Safari con la correzione per bug 28758 supporta eventi speciali chiamati " pageshow " e " pagehide " ;.

References:

Ho riscontrato un problema che il mio js non stava eseguendo quando l'utente aveva fatto clic su avanti o indietro. Per prima cosa ho deciso di fermare la memorizzazione nella cache del browser, ma questo non sembrava essere il problema. Il mio javascript era impostato per essere eseguito dopo che tutte le librerie ecc. Erano state caricate. Ho controllato questi con l'evento readyStateChange.

Dopo alcuni test ho scoperto che il readyState di un elemento in una pagina in cui è stato fatto clic su back non è "caricato" ma "completo". Aggiunta di || element.readyState == 'complete' alla mia dichiarazione condizionale ha risolto i miei problemi.

Ho pensato di condividere le mie scoperte, speriamo che possano aiutare qualcun altro.

Modifica per completezza

Il mio codice era il seguente:

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

Nell'esempio di codice sopra la variabile di script c'era un elemento di script appena creato che era stato aggiunto al DOM.

OK, ecco una soluzione finale basata sulla soluzione iniziale di ckramer e sull'esempio del cavallo da corsa che funziona in tutti i browser, incluso Opera. Se imposti history.navigationMode su 'compatibile', la funzione pronta di jQuery si attiverà sulle operazioni del pulsante Indietro in Opera e sugli altri principali browser.

Questa pagina contiene maggiori informazioni .

Esempio:

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

Ho provato questo in Opera 9.5, IE7, FF3 e Safari e funziona in tutti loro.

Non sono riuscito a far funzionare gli esempi sopra. Volevo semplicemente attivare un aggiornamento di alcune aree div modificate quando torni alla pagina tramite il pulsante Indietro. Il trucco che ho usato è stato impostare un campo di input nascosto (chiamato "bit sporco") su 1 non appena le aree div sono cambiate rispetto all'originale. Il campo di input nascosto mantiene effettivamente il suo valore quando faccio clic indietro, quindi onload posso verificare questo bit. Se è impostato, aggiorno la pagina (o semplicemente aggiorno i div). Sul caricamento originale, tuttavia, il bit non è impostato, quindi non perdo tempo a caricare la pagina due volte.

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

E si innescherebbe correttamente ogni volta che ho fatto clic sul pulsante Indietro.

Se ricordo bene, l'aggiunta di un evento unload () significa che la pagina non può essere memorizzata nella cache (nella cache in avanti / indietro) - perché il suo stato cambia / può cambiare quando l'utente si allontana. Quindi - non è sicuro ripristinare lo stato dell'ultimo secondo della pagina quando si ritorna ad essa navigando attraverso l'oggetto della cronologia.

Ho pensato che questo sarebbe stato per "onunload", non per il caricamento della pagina, dal momento che non stiamo parlando di lanciare un evento quando si colpisce " Back " ;? $ document.ready () è per gli eventi desiderati al caricamento della pagina, indipendentemente da come si arriva a quella pagina (ad es. reindirizzamento, apertura diretta del browser all'URL, ecc.), non quando si fa clic su " Indietro " ;, a meno che non si sia parlando di cosa sparare sulla pagina precedente quando si carica di nuovo. E non sono sicuro che la pagina non venga memorizzata nella cache poiché ho scoperto che lo sono ancora i Javascripts, anche quando $ document.ready () è incluso in essi. Abbiamo dovuto premere Ctrl + F5 durante la modifica dei nostri script che presentano questo evento ogni volta che li revisioniamo e vogliamo testare i risultati nelle nostre pagine.

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

è ciò che vorresti per un evento onunload quando colpisci " Indietro " e scaricando la pagina corrente, e si attiva anche quando un utente chiude la finestra del browser. Sembrava più quello che si desiderava, anche se sono più numeroso delle risposte $ document.ready (). Fondamentalmente la differenza è tra un evento che si attiva sulla pagina corrente mentre è in chiusura o su quello che si carica quando si fa clic su " Indietro " mentre si sta caricando. Testato in IE 7 bene, non posso parlare per gli altri browser in quanto non sono ammessi dove siamo. Ma questa potrebbe essere un'altra opzione.

Posso confermare a ckramer che l'evento pronto di jQuery funziona in IE e FireFox. Ecco un esempio:

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

per le persone che non vogliono usare l'intera libreria jquery ho estratto l'implementazione in un codice separato. È grande solo 0,4 KB.

Puoi trovare il codice, insieme a un tutorial tedesco in questo wiki: http://www.easy-coding.de/wiki/html-ajax-und- co / onload-evento-cross-browser-kompatibler-domcontentloaded.html

jQuery's ready è stato creato proprio per questo tipo di problema. Potresti voler esaminare l'implementazione per vedere cosa sta succedendo sotto le copertine.

Bill, oso rispondere alla tua domanda, tuttavia non sono sicuro al 100% con le mie ipotesi. Penso che altri browser IE quando portano l'utente a una pagina della cronologia non solo caricheranno la pagina e le sue risorse dalla cache, ma ripristineranno anche l'intero stato DOM (lettura della sessione). Internet Explorer non esegue il ripristino del DOM (o al momento del leasing) e quindi l'evento onload sembra essere necessario per una corretta reinizializzazione della pagina.

Ho provato la soluzione da Bill usando $ (documento). Già ... ma all'inizio non ha funzionato. Ho scoperto che se lo script viene inserito dopo la sezione HTML, non funzionerà. Se è la sezione head funzionerà, ma solo in IE. Lo script non funziona in Firefox.

OK, l'ho provato e funziona in Firefox 3, Safari 3.1.1 e IE7 ma non in Opera 9.52.
Se si utilizza l'esempio mostrato di seguito (basato sull'esempio del cavallo da corsa), al primo caricamento della pagina viene visualizzata una finestra di avviso. Ma se poi vai a un altro URL e quindi premi il pulsante Indietro per tornare a questa pagina, non visualizzi una finestra di avviso in Opera (ma lo fai negli altri browser).

Comunque, penso che questo sia abbastanza vicino per ora. Grazie a tutti!

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

L'evento di scaricamento non funziona correttamente su IE 9. L'ho provato con l'evento di caricamento (onload ()), funziona correttamente su IE 9 e FF5 .

Esempio:

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

Ho usato un modello html. Nel file custom.js di questo modello, c'era una funzione come questa:

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

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

    });

Ma questa funzione non funzionava quando torno indietro dopo andare su un'altra pagina.

Quindi, ho provato questo e ha funzionato:

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

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

Ora ho 2 "pronti" ma non dà alcun errore e la pagina funziona molto bene.

Tuttavia, devo dichiarare che è stato testato su Windows 10 - Opera v53 e Edge v42 ma nessun altro browser. Tieni presente questo ...

Nota: la versione di jquery era 3.3.1 e la versione di migrazione era 3.0.0

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top