Dopo essere tornato indietro nella cronologia di Firefox, JavaScript non verrà eseguito


84

Quando utilizzo il pulsante Indietro su Firefox per raggiungere una pagina visitata in precedenza, gli script su quella pagina non verranno più eseguiti .

Esistono soluzioni / soluzioni alternative per eseguire nuovamente gli script quando si visualizza la pagina per la seconda volta?

Tieni presente che ho testato le stesse pagine su Google Chrome e Internet Explorer e funzionano come previsto.


Ecco i file e i passaggi che ho usato per testare il problema:

(vai a 0.html, fai clic per arrivare a 1.html, pulsante Indietro)

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>

Risposte:


93

Imposta una funzione vuota da chiamare su window.onunload:

window.onunload = function(){}; 

per esempio

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

Fonte: http://www.firefoxanswer.com/firefox/672-firefoxanswer.html (versione archiviata)


2
Grazie, funziona. Qualche suggerimento su cosa fa il gestore onunload predefinito? (ad esempio, sto sovrascrivendo un comportamento predefinito di qualche tipo qui?)
Patonza

Ok grazie, indagherò. Grazie ancora, questo problema mi perseguita da un po ':)
Patonza

qualcuno sa perché FireFox ha bisogno di questo mentre altri browser no?
Pim Jager

7
Non stai sovrascrivendo nulla, questo impedisce solo a Firefox di memorizzare la pagina nella cache back-forward (bfcache). developer.mozilla.org/en/DOM/window.onunload developer.mozilla.org/En/Using_Firefox_1.5_caching
Chris Haas

1
Anche se dovrebbe rompere bfcache, purtroppo sembra che ricordi ancora la pagina precedente - in particolare, gli URL iframe che sono stati caricati vengono caricati di nuovo quando torni indietro e se il contenuto generato deve essere posizionato nel frame, non sembra esserci crossbrowser modo per rinfrescarlo di nuovo.
NoBugs

76

Quando utilizzo il pulsante Indietro su Firefox per raggiungere una pagina visitata in precedenza, gli script su quella pagina non verranno più eseguiti.

È corretto e questa è una buona cosa.

Quando si colpisce un collegamento in Firefox (e Safari e Opera), non distrugge immediatamente la tua pagina per passare a quella successiva. Mantiene intatta la pagina, semplicemente nascondendola alla vista. Se premi il pulsante Indietro, la vecchia pagina tornerà in vista, senza dover caricare nuovamente il documento; questo è molto più veloce, risultando in transizioni di pagina avanti / indietro più fluide per l'utente.

Questa funzionalità è chiamata bfcache .

Qualsiasi contenuto aggiunto alla pagina durante il caricamento precedente dell'utente e il suo utilizzo sarà ancora lì. Tutti i gestori di eventi che hai allegato agli elementi della pagina saranno comunque allegati. Eventuali timeout / intervalli impostati saranno ancora attivi. Quindi raramente c'è motivo per cui devi sapere di essere stato nascosto e mostrato nuovamente. Sarebbe sbagliato richiamare onloado incorporare nuovamente il codice dello script, perché qualsiasi associazione e generazione di contenuto eseguita in quella funzione verrebbe eseguita una seconda volta sullo stesso contenuto, con risultati potenzialmente disastrosi. (es. document.writenello script inline distruggerebbe completamente la pagina.)

Il motivo per cui scrivere in window.onunloadha un effetto è che i browser che implementano bfcache hanno deciso che, per compatibilità con le pagine che hanno davvero bisogno di sapere quando vengono scartate, qualsiasi pagina che dichiari interesse a sapere quando si onunloadverifica farà sì che bfcache a essere disabilitato. Quella pagina verrà caricata di nuovo quando torni ad essa, invece di essere recuperata da bfcache.

Quindi, se imposti window.onunload= function() {};, ciò che stai effettivamente facendo è deliberatamente rompere il bfcache. Ciò comporterà una navigazione lenta nelle tue pagine e non dovrebbe essere utilizzata se non come ultima risorsa.

Se hai bisogno di sapere quando l'utente lascia o torna alla tua pagina, senza rovinare il bfcache, puoi invece intercettare gli eventi onpageshowe onpagehide:

window.onload=window.onpageshow= function() {
    alert('Hello!');
};

4
Il mio problema è che bfcache non memorizza TUTTA la pagina nella cache, quindi devo rieseguire js per ricostruire il contenuto perso. Quindi battere l'intera pagina potrebbe essere ok. Ad ogni modo, non sto usando l'evento window.onload, sto usando l'evento jQuery document.ready. Conosci un modo per poter ancora usare document.ready ed evitare questo problema?
Patonza

bfcache dovrebbe in generale restituire l'intera pagina com'era quando è stata lasciata. Qual è il contenuto che manca dopo essere tornato dalla pagina precedente? (test case?) document.readyfunzionerà essenzialmente allo stesso modo di window.onload(per alcuni browser, sono comunque lo stesso evento).
bobince

14
NON è una buona cosa perché non esegue nuovamente il javascript, considerando che è memorizzato nella cache ... ma in realtà NON memorizza nella cache le modifiche che il javascript aveva apportato in precedenza. Se il javascript si dissolve in un elemento al caricamento della pagina, non lo sbiadisce di nuovo quando si visita nella cronologia ... ma lo fa ripartire con 0 opacità, annullando ciò che aveva fatto il javascript! Deve essere TUTTO O NIENTE. È necessario memorizzare nella cache lo stato completo della pagina dopo che il javascript è stato eseguito se si desidera presentarlo nella cache senza eseguire nuovamente il javascript!
Jimbo Jonny

1
@Jimbo: caso di prova per favore. bfcache ha lo scopo di (e in ogni caso che abbia mai visto, lo fa) preservare lo stato esatto del DOM su nascondi / mostra. Un elemento che era stato sfumato rimarrà opaco quando si torna alla pagina, a meno che qualche altro script non venga eseguito per nasconderlo di nuovo.
bobince

1
@bobince - Crea un elemento con un file CSS impostando l'opacità a zero e poi usa un po 'di jQuery per renderlo pronto per la dissolvenza in entrata nel documento. Tornando indietro nella storia, riapplicherà il foglio di stile CSS (lo zero) senza mantenere l'opacità: 1 che il JS ha aggiunto all'attributo style quando lo dissolve. La prima volta che visiti la pagina l'elemento verrà visualizzato in dissolvenza da zero a 1. Vai su un'altra pagina e rispondi e rimarrà lì completamente trasparente.
Jimbo Jonny

24

Puoi controllare la persistedproprietà pageshowdell'evento. È impostato su false al caricamento iniziale della pagina. Quando la pagina viene caricata dalla cache, è impostata su true.

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

Per qualche motivo jQuery non ha questa proprietà nell'evento. Puoi trovarlo dall'evento originale però.

$(window).bind("pageshow", function(event) {
    if (event.originalEvent.persisted) {
        alert("From bfcache");
    }
});

Grazie per aver fornito entrambe le versioni javascript e jquery! Ti sei perso una parentesi stretta alla fine lì (questo non è un gemito!). Noterò anche, per il bene degli altri, che il rapporto di IE e Chrome .persisted è sempre falso, a prescindere.
Magnus Smith

Come notato da Magnus, questo non ha funzionato per me in Chrome fino a quando non ho rimosso l'istruzione if.
Justin

Questo ha funzionato per me in Chrome 58.0.3029.110 (64 bit) e FF 53.0.2 (64 bit) senza alcuna modifica.
kmoser

1

Collega un evento "onunload" che non fa nulla:

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

Non sono sicuro, ho dato un voto
positivo

dovresti aggiungere alla tua risposta che l'aggiunta dell'evento onunload alla tua pagina disabiliterà effettivamente la pagina che viene memorizzata nella cache nella sua interezza. Questo non fa semplicemente eseguire di nuovo il JS, ma farà anche aumentare il carico del server. Questo non è davvero un suggerimento da prendere alla leggera, questo dovrebbe essere attentamente considerato.
dreagan

@dreagan, questo disabilita bfcache ma non necessariamente la cache HTTP. La cache HTTP ha un intero altro insieme di regole. Se lanci una sospensione lato server lì dentro dovresti notarlo durante il clic di ritorno. Mozilla ne parla nella terza domanda nelle FAQ per BFCache .
Chris Haas,

Stavo parlando del BFcache, avrei dovuto specificarlo. Ciò non significa che dovresti dare un suggerimento come questo senza informare l'OP delle conseguenze. Un'alternativa potrebbe essere quella di utilizzare l'evento onpopstate per provare a riattivare javascript.
Dreagan,

Non so ancora se ho capito. Perché "il carico del server dovrebbe salire di una tacca" se la bfcache locale del client viene bypassata? Sì, il DOM dovrà essere ricostruito, ma l'HTML dovrebbe far parte della cache HTTP del client. Sì, sarà necessario ricaricare ulteriori risorse, ma anche quelle dovrebbero far parte della cache HTTP del client. Per quanto riguarda onpopstate, quando questa domanda è stata posta quasi cinque anni fa, quell'evento era ancora relativamente nuovo e il supporto del browser era molto incoerente
Chris Haas,

1

Per quanto ne so, Firefox non onLoadattiva l'evento sul retro.

Dovrebbe attivare onFocus invece in base a questo collegamento qui .


Testato e windows.onfocus viene effettivamente chiamato, anche senza impostare il gestore vuoto window.onunload. L'impostazione di onunload è una soluzione leggermente migliore, ma anche .onfocus dovrebbe andare bene. Grazie :)
Patonza

1

Un modo semplice per fare in modo che una pagina esegua JavaScript quando l'utente vi torna indietro utilizzando la cronologia del browser è l'evento OnPopState. Lo usiamo per mettere in pausa e riprodurre il video sulla nostra home page ( https://fynydd.com ).

window.onpopstate = function() {

    // Do stuff here...
};

0

per alcuni casi come il listener di modifica dell'URL delle operazioni ajax può essere utilizzato

$(window).on('hashchange', function() {
        ....
});
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.