Modifier l'URL de la barre d'adresses dans l'application AJAX pour correspondre à l'état actuel

166

J'écris une application AJAX, mais au fur et à mesure que l'utilisateur se déplace dans l'application, j'aimerais que l'URL de la barre d'adresse se mette à jour malgré le manque de recharges de page. En gros, j'aimerais qu'ils soient en mesure de créer un signet à tout moment et de revenir ainsi à l'état actuel.

Comment les gens gèrent-ils le maintien de RESTfulness dans les applications AJAX?

jasonjwwilliams
la source
2
Il est utilisé pour maintenir l'état de vos applications, mais n'a rien à voir avec "RESTfulness".
Mohamed
29
window.history.pushState(null,'hi','page1?id=32')
Omu
3
la réponse acceptée a été écrite il y a 5 ans et entre-temps, nous avons obtenu window.history.pushState, tout comme @Omu l'a dit. l'emplacement.hash a apporté de nombreux problèmes et il est préférable de l'éviter.
pcarvalho
J'ai modifié la réponse pour mettre en évidence l'approche pushState.
jasonjwwilliams

Réponses:

116

La façon de faire est de manipuler location.hashlorsque les mises à jour AJAX entraînent un changement d'état que vous souhaitez avoir une URL discrète. Par exemple, si l'URL de votre page est:

http://example.com/

Si une fonction côté client a exécuté ce code:

// AJAX code to display the "foo" state goes here.

location.hash = 'foo';

Ensuite, l'URL affichée dans le navigateur serait mise à jour pour:

http://example.com/#foo

Cela permet aux utilisateurs de mettre en signet l'état «foo» de la page et d'utiliser l'historique du navigateur pour naviguer entre les états.

Avec ce mécanisme en place, vous devrez ensuite analyser la partie hachée de l'URL côté client à l'aide de JavaScript pour créer et afficher l'état initial approprié, car les identificateurs de fragment (la partie après le #) ne sont pas envoyés au serveur.

Le plugin hashchange de Ben Alman fait de ce dernier un jeu d'enfant si vous utilisez jQuery.

Dave Ward
la source
Vous avez raison. C'est la seule approche. Cela semble être une bonne explication détaillée de votre conseil: < ajaxpatterns.org/Unique_URLs >
jasonjwwilliams
@buymeasoda Merci pour la modification; Je ne sais pas trop à quoi je pensais quand j'ai écrit cette partie.
Dave Ward
1
Wow, cette réponse a été très utile. Bien que les exemples d'URL soient un peu déroutants, SO peut remplacer automatiquement les liens par des titres. Que diriez-vous de les remplacer par quelque chose comme example.com et example.com/#foo, afin que nous puissions voir l'URL entière en texte brut.
Neil
4
@Pascal Vous pouvez, mais uniquement dans les navigateurs prenant en charge pushState de HTML5. Bonne info à ce sujet ici: diveintohtml5.info/history.html
Dave Ward
1
J'ai fini par être un grand fan de history.js pour couvrir les bases de la compatibilité des navigateurs github.com/andreasbernhard/history.js
jocull
18

Regardez des sites comme book.cakephp.org. Ce site modifie l'URL sans utiliser le hachage et utilise AJAX. Je ne sais pas comment cela fonctionne exactement, mais j'ai essayé de le comprendre. Si quelqu'un sait, faites le moi savoir.

Aussi github.com lorsque vous regardez une navigation dans un certain projet.

daniel.wright
la source
J'ai remarqué cela avec GitHub il y a environ une semaine. Comment diable font-ils ça? Doit revenir en arrière et vérifier.
Drew Noakes le
16
Ils semblent utiliser la fonction javascript pushState (). Cela ajoute à l'historique de votre navigateur. Regardez dedans; c'est assez intéressant et cool.
daniel.wright
Merci pour cela, c'était exactement ce que je cherchais. Je m'étais demandé comment github le faisait. Au début, je pensais qu'il devait être rechargé mais il n'y avait que des requêtes AJAX. Dans Opera, il a rechargé la page.
kamranicus
Une technique similaire est utilisée par fb lors de la navigation dans les pages de différents groupes. Vous avez une colonne de navigation à gauche dans laquelle différents groupes sont mentionnés. Lorsque vous cliquez sur un nom de groupe particulier, l'URL change et seul le contenu du volet de contenu principal change avec l'URL (pas de hachage). Ainsi, lorsque l'utilisateur recharge la page, il n'est pas redirigé vers la page d'accueil mais vers la page des groupes.
Madeyedexter
11

Ceci est similaire à ce que Kevin a dit. Vous pouvez avoir l'état de votre client en tant qu'objet javascript, et lorsque vous souhaitez enregistrer l'état, vous sérialisez l'objet (en utilisant le codage JSON et base64). Vous pouvez ensuite définir le fragment de href sur cette chaîne.

var encodedState = base64(json(state));
var newLocation = oldLocationWithoutFragment + "#" + encodedState;

document.location = newLocation; // adds new entry in browser history
document.location.replace(newLocation); // replaces current entry in browser history

La première méthode traitera le nouvel état comme un nouvel emplacement (le bouton de retour les amènera donc à l'emplacement précédent). Ce dernier ne le fait pas.


la source
Existe-t-il un moyen d'ajouter une entrée à l'historique des signets sans actualiser la page? La définition de l'emplacement (comme dans votre premier exemple) provoquera une actualisation, n'est-ce pas?
Drew Noakes
faire document.location.replace redirigera également le navigateur vers cette URL (je viens de l'essayer dans la console chrome)
Omu
3

SWFAddress fonctionne dans les projets Flash et Javascript et vous permet de créer des URL de signet (en utilisant la méthode de hachage mentionnée ci-dessus) ainsi que de vous donner la prise en charge des boutons de retour.

http://www.asual.com/swfaddress/


la source
3

La méthode window.location.hash est la manière préférée de faire les choses. Pour une explication sur la façon de le faire, Ajax Patterns - URL uniques .

YUI a une implémentation de ce modèle en tant que module, qui comprend des travaux spécifiques à IE pour faire fonctionner le bouton de retour avec la réécriture de l'adresse à l'aide du hachage. Gestionnaire de l'historique du navigateur YUI .

D'autres frameworks ont également des implémentations similaires. Le point important est que si vous voulez que l'historique fonctionne avec la réécriture de l'adresse, les différents navigateurs ont besoin de différentes manières de la gérer. (Ceci est détaillé dans le premier article de lien.)

IE a besoin d'un hack basé sur iframe, où Firefox produira un double historique en utilisant la même méthode.

Drew Noakes
la source
3

Si OP ou d'autres recherchent encore un moyen de modifier l'historique du navigateur pour activer l'état, utiliser pushState et replaceState, comme suggéré par IESUS, est la `` bonne '' façon de le faire maintenant. Son principal avantage par rapport à location.hash semble être qu'il crée des URL réelles, pas seulement des hachages. Si l'historique du navigateur à l'aide des hachages est enregistré, puis revisité avec javascript désactivé, l'application ne fonctionnera pas, car les hachages ne sont pas envoyés au serveur. Cependant, si pushState a été utilisé, la route entière sera envoyée au serveur, que vous pouvez ensuite créer pour répondre de manière appropriée aux routes. J'ai vu un exemple où les mêmes modèles de moustache étaient utilisés à la fois du côté serveur et du côté client. Si le client avait activé javascript, il obtiendrait des réponses rapides en évitant l'aller-retour vers le serveur, mais l'application fonctionnerait parfaitement sans javascript. Ainsi, l'application peut se dégrader gracieusement en l'absence de javascript.

De plus, je pense qu'il existe un cadre, avec un nom comme history.js. Pour les navigateurs prenant en charge HTML5, il utilise pushState, mais si le navigateur ne le prend pas en charge, il revient automatiquement à utiliser des hachages.

Neil
la source
2

Vérifiez si l'utilisateur est «dans» la page, lorsque vous cliquez sur la barre d'url, javascript indique que vous êtes hors de la page. Si vous changez la barre d'url et appuyez sur 'ENTRER' avec le symbole '#' à l'intérieur, vous revenez dans la page, sans cliquer manuellement sur la page avec le curseur de la souris, puis une commande d'événement de chargement de touches (document.onkeypress) de javascript sera être en mesure de vérifier si c'est entrer et activer le javascript pour la redirection. Vous pouvez vérifier si l'utilisateur est dans la page avec window.onfocus et vérifier s'il est dehors avec window.onblur.

Ouais, c'est possible.

;)

Marcelo
la source
C'est la façon dont j'ai vu élégant pour changer la page lorsque l'utilisateur modifie la barre d'url avec le symbole #.
Marcelo