Actualizaciones de Ajax, botón de retroceso y DOM

113

Si javascript modifica DOM en la página A, el usuario navega a la página B y luego presiona el botón Atrás para volver a la página A. Todas las modificaciones al DOM de la página A se pierden y se le presenta al usuario la versión que se recuperó originalmente del servidor.

Funciona de esa manera en stackoverflow, reddit y muchos otros sitios web populares. (intente agregar un comentario de prueba a esta pregunta, luego navegue a una página diferente y presione el botón Atrás para regresar; su comentario desaparecerá)

Esto tiene sentido, sin embargo, algunos sitios web (apple.com, basecamphq.com, etc.) de alguna manera están obligando al navegador a ofrecer al usuario el estado más reciente de la página. (vaya a http://www.apple.com/ca/search/?q=ipod , haga clic en el enlace de descargas en la parte superior y luego haga clic en el botón Atrás; se conservarán todas las actualizaciones de DOM)

¿De dónde viene la inconsistencia?

lubos hasko
fuente
Curiosamente, Apple está recordando el estado sin modificar el hash .. hmmm
James
Miradas de Apple como que están simplemente manipulando el almacenamiento en caché la respuesta
BigBlondeViking
Como otros ya han sugerido, esto no es algo relacionado con javascript o ajax. Debe eliminar esas etiquetas para obtener respuestas correctas.
BYK
El ejemplo de Apple es pobre. Si contrata un área de búsqueda [ex: productos], haga clic en su enlace, luego presione atrás, el DOM no se conserva. está buscando una solución hash que muchos han sugerido.
BigBlondeViking
Cuando presioné el botón Atrás, Apple no recuerda en qué página de resultados de búsqueda estaba. Usando IE7. Necesitas una solución hash. Ver: Facebook.
Josh Stodola

Respuestas:

106

Una respuesta: entre otras cosas, los eventos de descarga hacen que se invalide la caché de retroceso / avance .

Algunos navegadores almacenan el estado actual de toda la página web en el llamado "bfcache" o "caché de página". Esto les permite volver a renderizar la página muy rápidamente cuando navegan a través de los botones de retroceso y avance, y preserva el estado del DOM y todas las variables de JavaScript. Sin embargo, cuando una página contiene eventos de descarga, esos eventos podrían poner la página en un estado no funcional y, por lo tanto, la página no se almacena en bfcache y debe recargarse (pero puede cargarse desde la caché estándar) y volver a cargarla. renderizado desde cero, incluida la ejecución de todos los controladores de carga. Al volver a una página a través de bfcache, el DOM se mantiene en su estado anterior, sin necesidad de activar controladores de carga (porque la página ya está cargada).

Tenga en cuenta que el comportamiento de bfcache es diferente del caché del navegador estándar con respecto a Cache-Control y otros encabezados HTTP. En muchos casos, los navegadores almacenarán en caché una página en bfcache incluso si de otra manera no la almacenarían en el caché estándar.

jQuery adjunta automáticamente un evento de descarga a la ventana, por lo que, desafortunadamente, el uso de jQuery descalificará su página para que no se almacene en bfcache para la preservación del DOM y retroceso / avance rápido. [Actualización: esto se ha corregido en jQuery 1.4 para que solo se aplique a IE]

Millas
fuente
3
lo clavaste totalmente. ambos, reddit y stackoverflow están usando jquery mientras que basecamp y apple están usando prototypejs. esto explica prácticamente todo.
lubos hasko
+1 interesante (aunque no en varios navegadores) la pregunta es muy diferente a cuando comenzó ...
BigBlondeViking
1
probablemente será en varios navegadores porque también puedo reproducirlo en mi Internet Explorer. Estoy seguro de que todos los navegadores web con JavaScript habilitado tuvieron que lidiar con este problema de todos modos. pero esto es realmente un desastre, cuando piensas en eso, el botón de retroceso siempre debe llevar a las personas a la página que vieron por última vez con todas las actualizaciones DOM, estado de javascript, etc., los desarrolladores no deberían romper esto haciendo algo en el evento de descarga y si lo hacen, los navegadores web no deberían intentar solucionar el problema sin utilizar bfcache en absoluto. Todo el evento de descarga es una gran broma. Estoy seguro de que el 99% de las veces se utiliza para reparar fugas de memoria.
lubos hasko
1
Específicamente, pérdidas de memoria IE. :) El evento de descarga de jQuery también soluciona un error (completamente no relacionado) en Firefox 2. Pero es innecesario para otros navegadores. dev.jquery.com/ticket/3015 Supongo que he oído hablar de otros usos para la descarga, como el seguimiento de clics salientes o el almacenamiento del estado de la aplicación web, pero nunca he tenido una razón para usarlo yo mismo, y si los desarrolladores quieren hacer su sitios más lentos y más dolorosos para sus usuarios (odio cómo la navegación de regreso a las páginas de comentarios de reddit restablece el estado de los comentarios contraídos), esa es su prerrogativa.
Miles
1
El evento de descarga solo se adjunta para IE, no para Firefox y Chrome. La última versión de safari conserva el estado dom sin que el desarrollador tenga que hacer nada.
David
15

He intentado que Chrome se comporte como lo hace Safari, y la única forma que he encontrado que funciona es configurar Cache-control: no-store los encabezados. Esto obliga al navegador a recuperar la página del servidor cuando el usuario presiona el botón Atrás. No es lo ideal, pero es mejor que se le muestre una página desactualizada.

nornagon
fuente
5
Ésta es la respuesta correcta a la pregunta original. Si desea forzar una recarga del servidor en el botón de retroceso, use el control de caché 'no-store, no-cache, must-revalidate'. Chrome quiere no tener tienda e IE quiere revalidar. Para otros navegadores (y w3c) no hay caché suficiente.
Miércoles
3

Facebook recuerda el estado de la página modificando el identificador de hash en la URL para las solicitudes ajax. Estos cambios se registran en el historial del navegador, por lo que cuando el usuario hace clic en el botón Atrás, el hash cambia a lo que era antes. Entonces, está implícito que necesitará algo de Javascript para monitorear el identificador de has y reaccionar cuando el navegador lo cambie. Andreas Blixt tiene disponible un script de monitoreo de hash .

Josh Stodola
fuente
a partir de hoy no muere, así que me puedes decir qué hace Facebook ahora
Ravinder Payal
3

Esto no tiene nada que ver con el símbolo de almohadilla (#).

Si revisa los encabezados HTTP de Apple, simplemente está almacenando la página en caché.

Luca Matteis
fuente
El ejemplo de Apple es pobre, no están "guardando" el estado de la página, su suposición de que el DOM se conserva incorrectamente
BigBlondeViking
2

El uso del identificador de hash / fragmento de URL es una forma bastante común de enganchar / recordar el estado en una aplicación web que depende de las actualizaciones de Ajax y DOM.

Consulte el proyecto Really Simple History para obtener algunas ideas. Es posible monitorear la URL en busca de cambios en el hash, y rsh lo hace, teniendo en cuenta las diferencias del navegador.

Pedro
fuente
1

Para cualquiera que Railstenga problemas con y esto, su problema no es bfcache (pensé que lo era), es la turbolinksjoya. A continuación se explica cómo eliminarlo.

Con suerte, esto le ahorrará algo de tiempo y le permitirá golpearse la cabeza contra la pared.

Yuval Karmi
fuente
0

Lo que busca es algún tipo de gestión de hash de URL. El # en la URL es solo para el cliente.

Cuando cambia el estado de la espalda con JS, actualiza los datos en el # de la URL.

También agrega algún tipo de sondeo que monitorea si el hash ha cambiado y carga el estado de la página en función de los nuevos datos en el hash.

Mira esto:

http://ajaxpatterns.org/Unique_URLs

BigRubiaViking
fuente
3
esto no tiene nada que ver con el símbolo de almohadilla.
Luca Matteis
3
Estás equivocado, está buscando la forma más común de preservar el estado de la página en una solución AJAX.
BigBlondeViking