Bibliothèque de gestion de l'historique Tout-en-un d'emplacement / hashchange

Tout d'abord, je sais qu'il existe des bibliothèques qui fournissent des polyfills pour l' location.pushState / popState ( History.js , Hash.js , jQuery hashchange ), alors n'hésitez pas à les lier.

J'ai besoin d'une bibliothèque plus puissante pour réaliser ce qui suit dans un RIA:

  1. L'utilisateur clique sur un lien
  2. La bibliothèque est notifiée et charge le contexte via Ajax (pas de rechargement complet!)
  3. Tous les éléments <a> sont exploités avec un gestionnaire de clics qui
    • Empêche la page de recharger en 2. ( preventDefault ) et
    • Appelle location.pushState place / définit location.hash pour les navigateurs plus anciens
  4. Le contenu chargé est inséré dans la page et remplace le contenu actuel
  5. Continuer avec 1.

En outre, le contenu précédemment chargé devrait être restauré à mesure que l'utilisateur navigue vers l'arrière.

Par exemple, klick via Google+ dans Internet Explorer <10 et tout autre navigateur.

Y a-t-il quelque chose qui soit encore proche? J'ai besoin de support pour IE8, FF10, Safari 5 et Chrome 18. De plus, il devrait avoir une licence permissive comme MIT ou Apache.

Je crois que Sammy.js ( http://sammyjs.org ) (licence MIT) se concentre le mieux sur ce que vous voulez faire, ses 2 piliers principaux étant:

  1. Routes
  2. Événements

Je pourrais citer les documents, mais c'est plutôt simple:

  • Configurez les itinéraires de clients qui se rapportent à des choses à faire, par exemple: mettre à jour la vue via ajax

  • Relier les événements aux itinéraires d'appel, par exemple: appeler l'itinéraire ci-dessus lorsque je clique sur un lien. (Vous devriez vous assurer que e.preventDefault est appelé dans l'événement défini que je crois, car il s'agit vraiment d'une décision d'application, de sorte que toute bibliothèque que vous allez utiliser imho ne peut pas être extraite

Quelques documents pertinents

Exemple pour un itinéraire: (à partir de http://sammyjs.org/docs/tutorials/json_store_1 )

  this.get('#/', function(context) { $.ajax({ url: 'data/items.json', dataType: 'json', success: function(items) { $.each(items, function(i, item) { context.log(item.title, '-', item.artist); }); } }); }); 

Ou quelque chose comme

  this.get('#/', function(context) { context.app.swap(''); ///the 'swap' here indicates a cleaning of the view //before partials are loaded, effectively rerendering the entire screen. NOt doing the swap enables you to do infinite-scrolling / appending style, etc. // ... }); 

Bien sûr, d'autres frameworks MVC-client pourraient également être une option, ce qui supprime encore plus de plomberie, mais peut-être une surpêche dans cette situation.

Une comparaison assez bonne (et encore assez récente)

http://codebrief.com/2012/01/the-top-10-javascript-mvc-frameworks-reviewed/ (j'utilise Spine.js moi-même).

Enfin, j'ai pensé qu'il serait utile d'inclure une réponse que j'ai écrite il y a quelque temps qui explique en détail les meilleures pratiques (comme je l'ai vu) dans des rafraîchissements côté client, etc. Peut-être que vous l'avez trouvé utile:

Accessibilité et tous ces frameworks JavaScript

J'utilise actuellement PathJS dans l'une de mes applications. C'est la meilleure décision que j'ai prise. Pour votre utilisation particulière, regardez l' exemple HTML5 .

Le code qui fait fonctionner l'exemple (à partir de la source):

 <script type="text/javascript"> // This example makes use of the jQuery library. // You can use any methods as actions in PathJS. You can define them as I do below, // assign them to variables, or use anonymous functions. The choice is yours. function notFound(){ $("#output .content").html("404 Not Found"); $("#output .content").addClass("error"); } function setPageBackground(){ $("#output .content").removeClass("error"); } // Here we define our routes. You'll notice that I only define three routes, even // though there are four links. Each route has an action assigned to it (via the // `to` method, as well as an `enter` method. The `enter` method is called before // the route is performed, which allows you to do any setup you need (changes classes, // performing AJAX calls, adding animations, etc. Path.map("/users").to(function(){ $("#output .content").html("Users"); }).enter(setPageBackground); Path.map("/about").to(function(){ $("#output .content").html("About"); }).enter(setPageBackground); Path.map("/contact").to(function(){ $("#output .content").html("Contact"); }).enter(setPageBackground); // The `Path.rescue()` method takes a function as an argument, and will be called when // a route is activated that you have not yet defined an action for. On this example // page, you'll notice there is no defined route for the "Unicorns!?" link. Since no // route is defined, it calls this method instead. Path.rescue(notFound); $(document).ready(function(){ // This line is used to start the HTML5 PathJS listener. This will modify the // `window.onpopstate` method accordingly, check that HTML5 is supported, and // fall back to hashtags if you tell it to. Calling it with no arguments will // cause it to do nothing if HTML5 is not supported Path.history.listen(); // If you would like it to gracefully fallback to Hashtags in the event that HTML5 // isn't supported, just pass `true` into the method. // Path.history.listen(true); $("a").click(function(event){ event.preventDefault(); // To make use of the HTML5 History API, you need to tell your click events to // add to the history stack by calling the `Path.history.pushState` method. This // method is analogous to the regular `window.history.pushState` method, but // wraps calls to it around the PathJS dispatched. Conveniently, you'll still have // access to any state data you assign to it as if you had manually set it via // the standard methods. Path.history.pushState({}, "", $(this).attr("href")); }); }); </script> 

PathJS possède certaines des fonctionnalités les plus recherchées d'une bibliothèque de routage:

  • Poids léger
  • Prend en charge l'API HTML5 History, la méthode 'onhashchange' et la dégradation gracieuse
  • Prise en charge des routes racines, des méthodes de sauvetage, des routes paramétrées, des composants d'itinéraire optionnels (itinéraires dynamiques) et une programmation orientée vers l'aspect
  • Bien testé (tests disponibles dans le répertoire ./tests)
  • Compatible avec tous les principaux navigateurs (Testé sur Firefox 3.6, Firefox 4.0, Firefox 5.0, Chrome 9, Opera 11, IE7, IE8, IE9)
  • Indépendant de toutes les bibliothèques de tiers, mais joue bien avec tous

J'ai trouvé les derniers points trop attrayants. Vous pouvez les trouver ici

J'espère que vous trouvez ça utile.

J'aimerais suggérer une combinaison de

Crossroads.js en tant que routeur http://millermedeiros.github.com/crossroads.js/

Et hacher pour gérer l'historique du navigateur et les URL de hash (w / plenty of fallback solutions): https://github.com/millermedeiros/hasher/ (basé sur http://millermedeiros.github.com/js-signals/ )

Cela nécessitera encore quelques lignes de code (pour charger un contenu ajax, etc.), mais vous donner des charges et d'autres possibilités lors de la gestion d'un itinéraire.

Voici un exemple en utilisant jQuery (aucune des bibliothèques ci-dessus requiert jQuery, je suis juste paresseux …)

http://fiddle.jshell.net/Fe5Kz/2/show/light

HTML

 <ul id="menu"> <li> <a href="foo">foo</a> </li> <li> <a href="bar/baz">bar/baz</a> </li> </ul> <div id="content"></div> 

JS

 //register routes crossroads.addRoute('foo', function() { $('#content').html('this could be ajax loaded content or whatever'); }); crossroads.addRoute('bar/{baz}', function(baz) { //maybe do something with the parameter ... //$('#content').load('ajax_url?baz='+baz, function(){ // $('#content').html('bar route called with parameter ' + baz); //}); $('#content').html('bar route called with parameter ' + baz); }); //setup hash handling function parseHash(newHash, oldHash) { crossroads.parse(newHash); } hasher.initialized.add(parseHash); hasher.changed.add(parseHash); hasher.init(); //add click listener to menu items $('#menu li a').on('click', function(e) { e.preventDefault(); $('#menu a').removeClass('active'); $(this).addClass('active'); hasher.setHash($(this).attr('href')); });​ 

Avez-vous examiné l' échantillon SPA de BigShelf (Single Page Application) de Microsoft? Il semble que cela couvre la façon de réaliser la plupart de ce que vous demandez.

Il utilise History.js, un objet wrapper personnalisé pour contrôler facilement la navigation appelé NavHistory et Knockout.js pour la gestion des clics.

Voici un flux de travail extrêmement abrégé sur la façon dont cela fonctionne: d'abord, vous devez initialiser un objet NavHistory qui enveloppe history.js et enregistre un rappel qui s'exécute lorsqu'il existe un changement de NavHistory ou d'hachage:

 var nav = new NavHistory({ params: { page: 1, filter: "all", ... etc ... }, onNavigate: function (navEntry) { // Respond to the incoming sort/page/filter parameters // by updating booksDataSource and re-querying the server } }); 

Ensuite, vous définirez un ou plusieurs modèles de vue Knockout.js avec des commandes qui peuvent être liées aux boutons de liens, etc.:

 var ViewModel = function (nav) { this.search = function () { nav.navigate({ page: 2, filter: '', ... }); // JSON object matching the NavHistory params }; } 

Enfin, dans votre balisage, vous utiliserez Knockout.js pour lier vos commandes à différents éléments:

 <a data-bind="click: search">...</a> 

Les ressources liées sont beaucoup plus détaillées en expliquant comment tout cela fonctionne. Malheureusement, ce n'est pas un cadre unique que vous cherchez, mais vous seriez surpris de voir combien il est facile de fonctionner.

Une autre chose, suite à l'exemple de BigShelf, le site que je construis est entièrement compatible avec les navigateurs, IE6 +, Firefox, Safari (mobile et de bureau) et Chrome (mobile et de bureau).

La AjaxTCR Library semble couvrir toutes les bases et contient des méthodes robustes que je n'ai pas vues auparavant. Il est publié sous licence BSD ( Open Source Initiative ).

Par exemple, voici cinq AjaxTCR.history(); Méthodes:

Init (onStateChangeCallback, initState);

AddToHistory (id, data, title, url, options);

Avoir tout();

GetPosition ();

EnableBackGuard (message, immédiat);

L' addToHistory(); ci-dessus addToHistory(); A suffisamment de paramètres pour permettre une liaison hash profonde dans les sites Web.

Plus de bonbons pour les yeux de .com.cookie () , .storage () et .template () fournit plus que des méthodes suffisantes pour gérer les besoins en données de session .

La page Web de l'API AjaxTCR bien documentée possède une pléthore d'informations avec les doctiles téléchargeables à démarrer!

Mise à jour du statut:
Ce site Web comporte également une section de page Web Exemples comprenant des fichiers .zip téléchargeables avec des fichiers de projet prêts à l'emploi ( Client ) et Back End ( Serveur ).

Il s'agit notamment des exemples prêts à l'emploi suivants:
Cookie à sens unique
HttpOnly Cookies
Histoire de voler
Explorateur d'histoire

Il existe un bon nombre d'autres exemples qui complètent le processus pour utiliser plusieurs de leurs méthodes API, ce qui facilite l'achèvement de la petite courbe d'apprentissage.

Plusieurs suggestions

  • ExtJs , voir leur exemple d'histoire , et voici les documents .
  • YUI Browser History Manager .
  • JQuery BBQ semble fournir un ensemble de fonctionnalités plus avancé sur jQuery.hashcode.
  • ReallySimpleHistory peut également être utile, bien qu'il soit assez ancien et peut-être dépassé.

Remarque: ExtJs History a été étendu pour optimiser les appels en double (redondants) pour add() .

PJAX est le processus que vous décrivez.

Les techniques de pjax les plus avancées commenceront même à précharger le contenu, lorsque l'utilisateur survolera le lien.

C'est une bonne bibliothèque pjax. https://github.com/MoOx/pjax

Vous marquez que les conteneurs dont ils ont besoin seront mis à jour sur les demandes suivantes:

 new Pjax({ selectors: ["title", ".my-Header", ".my-Content", ".my-Sidebar"] }) 

Ainsi, dans ce qui précède, seul le title , l'en .my-header , le .my-content .my-sidebar seront remplacés par le contenu de l'appel ajax.

Des choses à surveiller

Faites attention à la façon dont votre JS se charge et détecte lorsque la page est prête. Le javascript ne sera pas rechargé sur de nouvelles pages. Faites également attention lorsque les appels d'analyse sont appelés, pour la même raison.