Ajax, bouton de retour et mises à jour DOM

113

Si javascript modifie le DOM dans la page A, l'utilisateur accède à la page B, puis clique sur le bouton de retour pour revenir à la page A. Toutes les modifications apportées au DOM de la page A sont perdues et l'utilisateur reçoit la version qui a été récupérée à l'origine sur le serveur.

Cela fonctionne de cette façon sur stackoverflow, reddit et de nombreux autres sites Web populaires. (essayez d'ajouter un commentaire de test à cette question, puis accédez à une page différente et appuyez sur le bouton retour pour revenir - votre commentaire sera "parti")

Cela a du sens, mais certains sites Web (apple.com, basecamphq.com, etc.) obligent en quelque sorte le navigateur à fournir à l'utilisateur le dernier état de la page. (allez sur http://www.apple.com/ca/search/?q=ipod , cliquez sur le lien de téléchargement en haut, puis cliquez sur le bouton retour - toutes les mises à jour DOM seront conservées)

d'où vient l'incohérence?

lubos hasko
la source
Fait intéressant, Apple se souvient de l'état sans modifier le hachage .. hmmm
James
Apple semble simplement manipuler la mise en cache des réponses
BigBlondeViking
Comme d'autres l'ont déjà suggéré, ce n'est pas quelque chose lié à javascript ou ajax. Vous devez supprimer ces balises pour obtenir des réponses correctes.
BYK
L'exemple d'Apple est médiocre. Si vous contractez une zone de recherche [ex: produits], cliquez sur votre lien, puis appuyez en arrière, le DOM n'est pas conservé. vous recherchez une solution de hachage que beaucoup ont suggérée.
BigBlondeViking
Lorsque j'ai appuyé sur le bouton de retour, Apple ne se souvient pas du tout de la page de résultats de recherche sur laquelle j'étais. Utilisation d'IE7. Vous avez besoin d'une solution de hachage. Voir: Facebook.
Josh Stodola

Réponses:

106

Une réponse: entre autres, les événements de déchargement entraînent l'invalidation du cache arrière / avant .

Certains navigateurs stockent l'état actuel de la page Web entière dans ce que l'on appelle «bfcache» ou «cache de page». Cela leur permet de restituer la page très rapidement lors de la navigation via les boutons Précédent et Suivant, et préserve l'état du DOM et de toutes les variables JavaScript. Cependant, lorsqu'une page contient des événements onunload, ces événements peuvent potentiellement mettre la page dans un état non fonctionnel, et ainsi la page n'est pas stockée dans le bfcache et doit être rechargée (mais peut être chargée à partir du cache standard) et re- rendu à partir de zéro, y compris l'exécution de tous les gestionnaires onload. Lors du retour sur une page via le bfcache, le DOM est conservé dans son état précédent, sans avoir besoin de déclencher des gestionnaires onload (car la page est déjà chargée).

Notez que le comportement du bfcache est différent du cache standard du navigateur en ce qui concerne Cache-Control et d'autres en-têtes HTTP. Dans de nombreux cas, les navigateurs mettront en cache une page dans le bfcache même s'il ne la stockerait pas autrement dans le cache standard.

jQuery attache automatiquement un événement de déchargement à la fenêtre, donc malheureusement, l'utilisation de jQuery disqualifiera votre page d'être stockée dans le bfcache pour la préservation du DOM et un retour / avance rapide. [Mise à jour: cela a été corrigé dans jQuery 1.4 afin qu'il ne s'applique qu'à IE]

Miles
la source
3
vous l'avez totalement cloué. tous deux, reddit et stackoverflow utilisent jquery tandis que basecamp et apple utilisent prototypejs. cela explique à peu près tout.
lubos hasko
+1 intéressant (pas cross browser cependant) la question est très différente de celle quand elle a commencé ...
BigBlondeViking
1
ce sera probablement cross-browser car je peux aussi le reproduire sur mon Internet Explorer. Je suis sûr que chaque navigateur Web avec javascript activé devait de toute façon faire face à ce problème. mais c'est vraiment un gâchis, quand on y pense, le bouton de retour devrait toujours amener les gens à la page qu'ils ont vue en dernier avec toutes les mises à jour du DOM, l'état javascript, etc. les développeurs ne devraient pas casser cela en faisant quelque chose dans l'événement de déchargement et s'ils le font, les navigateurs Web ne devraient pas essayer de résoudre le problème en n'utilisant pas du tout bfcache. tout l'événement de déchargement est une grosse blague. Je suis sûr que 99% du temps, il est utilisé pour corriger les fuites de mémoire.
lubos hasko le
1
Plus précisément, la mémoire IE fuit. :) L'événement de déchargement jQuery corrige également un bogue (totalement indépendant) dans Firefox 2. Mais il n'est pas nécessaire pour les autres navigateurs. dev.jquery.com/ticket/3015 Je suppose que j'ai entendu parler d'autres utilisations pour onunload, comme le suivi des clics sortants ou la sauvegarde de l'état de l'application Web, mais je n'ai jamais eu de raison de l'utiliser moi-même, et si les développeurs veulent faire leur les sites plus lents et plus douloureux pour leurs utilisateurs (je déteste la façon dont le retour aux pages de commentaires reddit réinitialise l'état de commentaire réduit), c'est leur prérogative.
Miles
1
L'événement de déchargement est uniquement attaché pour IE et non pour Firefox et Chrome. La dernière version de safari préserve l'état dom sans que le développeur n'ait à faire quoi que ce soit.
David
15

J'ai essayé de faire en sorte que Chrome se comporte comme Safari, et le seul moyen que j'ai trouvé que cela fonctionne est de définir les Cache-control: no-storeen-têtes. Cela oblige le navigateur à récupérer la page à partir du serveur lorsque l'utilisateur appuie sur le bouton Précédent. Pas idéal, mais mieux que de voir une page obsolète.

Nornagon
la source
5
C'est la bonne réponse à la question initiale. Si vous voulez forcer un rechargement du serveur sur le bouton de retour, utilisez le contrôle de cache 'no-store, no-cache, must-revalidate'. Chrome ne veut pas de magasin et IE veut une revalidation incontournable. Pour les autres navigateurs (et w3c), aucun cache n'est suffisant.
woens
3

Facebook se souvient de l'état de la page en modifiant l'identifiant de hachage dans l'URL pour les requêtes ajax. Ces modifications sont enregistrées dans l'historique du navigateur, de sorte que lorsque l'utilisateur clique sur le bouton Précédent, le hachage change à ce qu'il était auparavant. Il est donc sous-entendu que vous aurez besoin de Javascript pour surveiller l'identifiant has et réagir lorsqu'il est modifié par le navigateur. Andreas Blixt a un script de surveillance de hachage disponible .

Josh Stodola
la source
à partir d'aujourd'hui, il ne meurt pas, alors je peux me dire ce que Facebook fait maintenant
Ravinder Payal
3

Cela n'a rien à voir avec le symbole dièse (#).

Si vous voulez vérifier les en-têtes HTTP d'Apple, c'est simplement la mise en cache de la page.

Luca Matteis
la source
L'exemple d'Apple est médiocre, ils ne "sauvegardent" pas l'état de la page, son hypothèse que le DOM est conservé mal
BigBlondeViking
2

L'utilisation de l'identifiant de hachage / fragment d'URL est un moyen assez courant de hooker / de mémoriser l'état dans une application Web qui repose sur les mises à jour Ajax et DOM.

Consultez le projet d' histoire vraiment simple pour quelques idées. Il est possible de surveiller l'URL pour les modifications apportées au hachage, et rsh le fait, en tenant compte des différences de navigateur.

Peter
la source
1

Pour quiconque a des problèmes avec Railset ceci - votre problème n'est pas bfcache (je pensais que c'était le cas) - c'est le turbolinksjoyau. Voici comment le supprimer.

J'espère que cela vous fera gagner du temps et vous cognera la tête contre le mur.

Yuval Karmi
la source
0

Ce que vous recherchez, c'est un type de gestion de hachage d'URL. Le # dans l'url est pour le côté client uniquement.

Lorsque vous modifiez l'état du dos avec JS, vous mettez à jour les données dans le # de l'url.

Vous ajoutez également un type d'interrogation qui surveille si le hachage a changé et charge l'état de la page en fonction des nouvelles données du hachage.

Regarde ça:

http://ajaxpatterns.org/Unique_URLs

BigBlondeViking
la source
3
cela n'a rien à voir avec le symbole de hachage.
Luca Matteis
3
Vous vous trompez, il recherche le moyen le plus courant de préserver l'état de la page dans une solution AJAX.
BigBlondeViking