Bon tutoriel sur l'utilisation de l'API HTML5 History (Pushstate?) [Fermé]

168

J'envisage d'utiliser l'API HTML5 History pour résoudre les problèmes de liens profonds avec le contenu chargé AJAX, mais j'ai du mal à décoller. Quelqu'un connaît-il de bonnes ressources?

Je veux l'utiliser car cela semble être un excellent moyen de permettre à ceux qui sont envoyés que les liens ne soient pas activés par JS. De nombreuses solutions échouent lorsque quelqu'un avec JS envoie un lien à quelqu'un sans.

Ma recherche initiale semble pointer vers une API History dans JS et la méthode pushState.

http://html5demos.com/history

Doux duvet
la source

Réponses:

181

Pour un excellent didacticiel, la page Mozilla Developer Network sur cette fonctionnalité est tout ce dont vous aurez besoin: https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history

Malheureusement, l'API HTML5 History est implémentée différemment dans tous les navigateurs HTML5 (ce qui la rend incohérente et boguée) et n'a pas de solution de secours pour les navigateurs HTML4. Heureusement, History.js offre une compatibilité croisée pour les navigateurs HTML5 (garantissant que tous les navigateurs HTML5 fonctionnent comme prévu) et fournit éventuellement un hachage de secours pour les navigateurs HTML4 (y compris la prise en charge maintenue des données, des titres, des fonctionnalités pushState et replaceState).

Vous pouvez en savoir plus sur History.js ici: https://github.com/browserstate/history.js

Pour un article sur l'API Hashbangs VS Hashes VS HTML5 History, voir ici: https://github.com/browserstate/history.js/wiki/Intelligent-State-Handling

balupton
la source
25
Prise automatique sans vergogne. Excellent post et plugin cependant. :)
Purag
28

Gardez à l'esprit lorsque vous utilisez HTML5 pushstate si un utilisateur copie ou marque un lien profond et le visite à nouveau, alors ce sera un coup de serveur direct qui sera 404 donc vous devez être prêt pour cela et même une bibliothèque pushstate js n'aidera pas tu. La solution la plus simple consiste à ajouter une règle de réécriture à votre serveur Nginx ou Apache comme ceci:

Apache (dans votre vhost si vous en utilisez un):

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /
    RewriteRule ^index\.html$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.html [L]
 </IfModule>

Nginx

rewrite ^(.+)$ /index.html last;
Mauvis Ledford
la source
TELLE est la vraie réponse. Ce n'est nulle part sur le wiki / tutoriels de History.js de Balupton, etc. En fait, History.js n'utilise pas de hachage, vous devez donc utiliser une redirection .htaccess!
adriendenat
13
Idéalement, votre serveur / application doit répondre à la route de manière appropriée sans avoir besoin de cette réécriture.
sholsinger
D'accord, sauf dans le cas de nombreux frameworks JavaScript modernes tels que Backbone.js, Spine, Ember, etc. Ce sont tous essentiellement des applications JavaScript "une page". On pourrait trouver une solution pour servir le modèle de backend d'écriture pour le référencement, etc., mais en attendant, cela serait nécessaire.
Mauvis Ledford
*droite. J'écris à ce sujet plus en détail ici: readystate4.com/2012/05/17/…
Mauvis Ledford
6

La spécification de l'historique HTML5 est bizarre.

history.pushState()ne envoie pas d' popstateévénement ni ne charge une nouvelle page par lui-même. Il s'agissait uniquement de pousser l'État dans l'histoire. Il s'agit d'une fonction «d'annulation» pour les applications d'une seule page. Vous devez distribuer manuellement un popstateévénement ou utiliser history.go()pour naviguer vers le nouvel état. L'idée est qu'un routeur puisse écouter les popstateévénements et faire la navigation à votre place.

Quelques points à noter:

  • history.pushState()et history.replaceState()ne pas envoyer d' popstateévénements.
  • history.back(), history.forward()et les boutons Précédent et Suivant du navigateur envoient des popstateévénements.
  • history.go()et history.go(0)faites un rechargement complet de la page et ne distribuez pas d' popstateévénements.
  • history.go(-1)(1 page précédente) et history.go(1)(1 page suivante) envoient des popstateévénements.

Vous pouvez utiliser l'API d'historique comme celle-ci pour pousser un nouvel état ET envoyer un événement popstate.

history.pushState({message:'New State!'}, 'New Title', '/link'); window.dispatchEvent(new PopStateEvent('popstate', { bubbles: false, cancelable: false, state: history.state }));

Ensuite, écoutez les popstateévénements avec un routeur.

Erik Ringsmuth
la source
1
Est-ce juste moi ou ne new PopStateEvent(...)semble pas fonctionner dans IE11? Y a-t-il une solution de contournement que tout le monde connaît?
David Alan Hjelle
On dirait que IE 11 a besoin de quelque chose comme: var pop_state_event = document.createEvent('Event'); pop_state_event.initEvent('popstate', true, true); window.dispatchEvent(pop_state_event);
David Alan Hjelle
4

Vous pouvez essayer Davis.js , il vous donne le routage dans votre JavaScript en utilisant pushState lorsqu'il est disponible et sans JavaScript, il permet à votre code côté serveur de gérer les demandes.

Oliver Nightingale
la source
4

Voici un grand écran-casting sur le sujet par Ryan Bates de railscasts. À la fin, il désactive simplement la fonctionnalité ajax si la méthode history.pushState n'est pas disponible:

http://railscasts.com/episodes/246-ajax-history-state

deb
la source
2

Vous voudrez peut-être jeter un coup d'œil à ce plugin jQuery. Ils ont de nombreux exemples sur leur site. http://www.asual.com/jquery/address/

Nathan Totten
la source
Encore une fois, cette solution semble échouer lorsque JS est désactivé. Je pense que l'API History a le pouvoir de fonctionner en conjonction avec modrewrite afin que les liens soient toujours traités dans la première instance par le serveur, sans avoir besoin de redirection depuis la couche JS.
Mild Fuzz
Vous êtes sur la bonne voie avec le modrewrite. La solution de gestion de l'API historique et de gestion lorsque l'utilisateur n'a pas JS sont en réalité deux choses distinctes. Si vous n'avez pas JS, vous devez gérer l'utilisateur avec des hrefs standard et des réponses de serveur. L'API d'historique pourrait être construite comme une sorte de "bon à avoir" si le navigateur de l'utilisateur la prend en charge.
Nathan Totten
Les exemples Express et State fournis avec jQuery Address 1.3 fonctionnent assez bien lorsque JavaScript est désactivé. Le second utilise PHP avec mod_rewrite.
Rostislav
Exactement mon tact. J'ai l'intention de créer le site sans JS, d'ajouter des éléments AJAX, puis d'utiliser l'historique pour réécrire l'URL, en préservant les liens profonds. Théoriquement, cela devrait être une meilleure méthode que toutes celles que j'ai vues car le site ne dépendra pas d'AJAX, à aucun moment
Mild Fuzz
1
-1 car jQuery Address n'est pas un port direct de l'API HTML5 State - ne prend pas en charge les données ou les titres, et replaceState.
balupton
2

J'ai écrit une abstraction de routeur très simple au-dessus de History.js, appelée StateRouter.js . C'est dans les tout premiers stades de développement, mais je l'utilise comme solution de routage dans une application d'une page que j'écris. Comme vous, j'ai trouvé History.js très difficile à comprendre, d'autant plus que je suis assez nouveau dans JavaScript, jusqu'à ce que je comprenne que vous avez vraiment besoin (ou devriez avoir) une abstraction de routage par-dessus, car il résout un bas niveau problème.

Cet exemple de code simple doit montrer comment il est utilisé:

var router = new staterouter.Router();
// Configure routes
router
  .route('/', getHome)
  .route('/persons', getPersons)
  .route('/persons/:id', getPerson);
// Perform routing of the current state
router.perform();

Voici un petit violon que j'ai concocté afin de démontrer son utilisation.

aknuds1
la source
1
Ce violon ne fonctionne pas pour moi dans Chrome sur Mac. Il jette une erreur. (Uncaught ReferenceError: staterouter is not defined)
DrewT
@DrewT Merci, le violon a été cassé à cause d'un changement sur github.com, mais j'ai contourné le problème.
aknuds1
Oui, je travaille maintenant, merci pour la réponse rapide.
DrewT
1

si jQuery est disponible, vous pouvez utiliser jQuery BBQ

sprugman
la source
Cela semble échouer avec JS désactivé.
Mild Fuzz
c'est probablement vrai - je ne l'ai pas regardé. Je pense que vous aurez ce problème avec toutes les approches basées sur js-library. Ils sont basés sur la manipulation de la partie hachée de l'url.
sprugman
1
c'est le but de l'API HTML5 History - ça ne casse rien
balupton
2
@MildFuzz Computer semble échouer sans source d'alimentation! Je pense que vous avez une erreur ID-10-T ...
Eric Hodonsky
1
Ironiquement, c'est vous qui avez mal compris
Mild Fuzz