Después de viajar al historial de Firefox, JavaScript no se ejecutará

84

Cuando uso el botón Atrás en Firefox para llegar a una página visitada anteriormente, los scripts de esa página no se ejecutarán nuevamente .

¿Existe alguna solución / solución alternativa para que los scripts se ejecuten nuevamente al ver la página por segunda vez?

Tenga en cuenta que he probado las mismas páginas en Google Chrome e Internet Explorer y funcionan según lo previsto.


Estos son los archivos y los pasos que utilicé para probar el problema:

(navegue a 0.html, haga clic para llegar a 1.html, botón de retroceso)

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
fuente

Respuestas:

92

Configure una función vacía para que se llame en window.onunload:

window.onunload = function(){}; 

p.ej

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

Fuente: http://www.firefoxanswer.com/firefox/672-firefoxanswer.html (versión archivada)

John Baber-Lucero
fuente
2
Gracias, funciona. ¿Alguna pista sobre qué hace el controlador onunload predeterminado? (por ejemplo, ¿estoy anulando un comportamiento predeterminado de algún tipo aquí?)
Patonza
Ok gracias, investigaré. Gracias de nuevo, este problema me ha estado atormentando por un tiempo :)
Patonza
¿Alguien sabe por qué FireFox necesita esto mientras que otros navegadores no?
Pim Jager
7
No está anulando nada, esto solo evita que Firefox almacene la página en la caché Back-Forward Cache (bfcache). developer.mozilla.org/en/DOM/window.onunload developer.mozilla.org/En/Using_Firefox_1.5_caching
Chris Haas
1
Si bien debería romper bfcache, lamentablemente, parece que todavía recuerda la página anterior; específicamente, las URL de iframe que se cargaron se cargan nuevamente cuando regresa, y si el contenido generado debe colocarse en el marco, no parece haber un navegador cruzado manera de refrescar eso de nuevo.
NoBugs
76

Cuando uso el botón Atrás en Firefox para llegar a una página visitada anteriormente, los scripts de esa página no se ejecutarán nuevamente.

Eso es correcto y eso es bueno.

Cuando pulsa un enlace en Firefox (y Safari y Opera), no destruye inmediatamente su página para pasar a la siguiente. Mantiene la página intacta, simplemente ocultándola de la vista. Si presiona el botón Atrás, volverá a ver la página anterior, sin tener que cargar el documento nuevamente; esto es mucho más rápido, lo que resulta en transiciones de página hacia atrás / adelante más suaves para el usuario.

Esta característica se llama bfcache .

Cualquier contenido que haya agregado a la página durante la carga y el uso anteriores del usuario seguirá estando allí. Todos los controladores de eventos que adjuntó a los elementos de la página seguirán estando adjuntos. Los tiempos de espera / intervalos que establezca seguirán activos. Por lo tanto, rara vez hay alguna razón por la que deba saber que lo han ocultado y vuelto a mostrar. Sería incorrecto volver a llamar onloado al código de secuencia de comandos en línea, porque cualquier enlace y generación de contenido que hiciera en esa función se ejecutaría una segunda vez sobre el mismo contenido, con resultados potencialmente desastrosos. (por ejemplo, document.writeen un script en línea destruiría totalmente la página).

La razón por la que escribir a window.onunloadtiene un efecto es que los navegadores que implementan bfcache han decidido que, por compatibilidad con las páginas que realmente necesitan saber cuándo se descartan, cualquier página que declare un interés en saber cuándo onunloadocurre hará que bfcache estar discapacitado. Esa página se cargará nueva cuando vuelva a ella, en lugar de recuperarse de bfcache.

Entonces, si configura window.onunload= function() {};, lo que realmente está haciendo es romper deliberadamente el bfcache. Esto hará que sus páginas sean lentas para navegar y no deben usarse excepto como último recurso.

Si necesita saber cuándo el usuario sale o vuelve a su página, sin estropear el bfcache, puede capturar los eventos onpageshowy en su onpagehidelugar:

window.onload=window.onpageshow= function() {
    alert('Hello!');
};
bobince
fuente
3
Mi problema es que bfcache no almacena en caché TODA la página, así que tengo que volver a ejecutar js para reconstruir el contenido perdido. Así que destrozar toda la página podría estar bien. De todos modos, no estoy usando el evento window.onload, estoy usando el evento jQuery document.ready. ¿Conoce alguna forma de poder seguir utilizando document.ready y evitar este problema?
Patonza
bfcache, en general, debería devolver la página completa como estaba cuando se dejó. ¿Cuál es el contenido que falta después de regresar de la página anterior? (¿caso de prueba?) document.readyfuncionará esencialmente de la misma manera que window.onload(para algunos navegadores, son el mismo evento de todos modos).
bobince
14
Eso NO es algo bueno porque no ejecuta el javascript nuevamente, considerando que está almacenado en caché ... pero en realidad NO almacena en caché los cambios que el javascript había realizado anteriormente. Si el javascript se desvanece en un elemento al cargar la página, no lo vuelve a desvanecer cuando se visita en el historial ... pero SÍ lo inicia en 0 opacidad nuevamente, deshaciendo lo que había hecho el javascript. Tiene que ser TODO O NADA. ¡Debe almacenar en caché el estado completo de la página después de que se haya ejecutado el javascript si desea presentarlo en caché sin ejecutar el javascript nuevamente!
Jimbo Jonny
1
@Jimbo: Caso de prueba, por favor. bfcache está destinado a (y en todos los casos que he visto, lo hace) preservar el estado exacto del DOM sobre hide / show. Un elemento que se ha desvanecido permanecerá opaco cuando se vuelva a la página, a menos que se ejecute algún otro script para ocultarlo nuevamente.
Bobince el
1
@bobince: cree un elemento con un archivo CSS que establezca la opacidad en cero y luego use algo de jQuery para que se desvanezca en el documento. Al retroceder en la historia, se volverá a aplicar la hoja de estilo CSS (el cero) sin mantener la opacidad: 1 que el JS agregó al atributo de estilo cuando se desvaneció. La primera vez que visite la página, el elemento se desvanecerá de cero a 1. Vaya a otra página y devuelva el golpe y se quedará allí completamente transparente.
Jimbo Jonny
23

Puede consultar la persistedpropiedad del pageshowevento. Se establece en falso en la carga de la página inicial. Cuando la página se carga desde la caché, se establece en verdadero.

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

Por alguna razón, jQuery no tiene esta propiedad en el evento. Sin embargo, puedes encontrarlo en el evento original.

$(window).bind("pageshow", function(event) {
    if (event.originalEvent.persisted) {
        alert("From bfcache");
    }
});
Mika Tuupola
fuente
¡Gracias por proporcionar las versiones javascript y jquery! Te perdiste un paréntesis cerrado al final (¡esto no es un gemido!). También señalaré, por el bien de los demás, que el informe de IE y Chrome .persisted siempre es falso, independientemente.
Magnus Smith
Como señaló Magnus, esto no funcionó para mí en Chrome hasta que eliminé la declaración if.
Justin
Esto funcionó para mí en Chrome 58.0.3029.110 (64 bits) y FF 53.0.2 (64 bits) sin ningún cambio.
kmoser
1

Conecte en un evento "onunload" que no hace nada:

<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
fuente
No estoy seguro, me dio un voto arriba, se parece a alguien que acaba de downvoted cada respuesta a esta pregunta ...
Patonza
debe agregar a su respuesta que agregar el evento onunload a su página realmente deshabilitará la página que se almacena en caché en su totalidad. Esto no solo hace que JS se ejecute nuevamente, sino que también hará que la carga del servidor suba un poco. En realidad, esta no es una sugerencia para tomar a la ligera, esto debe considerarse cuidadosamente.
dreagan
@dreagan, esto deshabilita el bfcache pero no necesariamente el caché HTTP. La caché HTTP tiene un conjunto de reglas completamente diferente. Si echas un sueño del lado del servidor allí, deberías notarlo durante el clic de regreso. Mozilla habla de esto en su tercera pregunta sobre las preguntas frecuentes de BFCache .
Chris Haas
Estaba hablando del BFcache, debería haberlo especificado. Eso no significa que deba dar una sugerencia como esta sin notificar al OP las consecuencias. Una alternativa sería usar el evento onpopstate para intentar disparar el javascript nuevamente.
dreagan
Todavía no sé si lo entiendo. ¿Por qué "la carga del servidor aumentaría un poco" si se pasa por alto el bfcache local del cliente? Sí, será necesario reconstruir el DOM, pero el HTML debe ser parte de la caché HTTP del cliente. Sí, será necesario volver a cargar recursos adicionales, pero también deberían ser parte de la caché HTTP del cliente. En cuanto a onpopstate, cuando se hizo esta pregunta hace casi cinco años, el evento aún era relativamente nuevo y el soporte del navegador era muy inconsistente
Chris Haas
1

Por lo que yo sé, Firefox no activa el onLoadevento en la parte posterior.

Debería activarse onFocus en su lugar basado en este enlace aquí .

sistema de salida
fuente
Lo probé y windows.onfocus de hecho se llama, incluso sin configurar el controlador window.onunload vacío. Configurar onunload es una solución un poco mejor, pero .onfocus también debería estar bien. Gracias :)
Patonza
1

Una forma sencilla de hacer que una página ejecute JavaScript cuando el usuario vuelve a ella utilizando el historial del navegador es el evento OnPopState. Usamos esto para pausar y reproducir el video en nuestra página de inicio ( https://fynydd.com ).

window.onpopstate = function() {

    // Do stuff here...
};
Michael A.
fuente
0

para algunos casos, como operaciones ajax, se puede usar el oyente de cambio de URL

$(window).on('hashchange', function() {
        ....
});
Domador
fuente