I. Préparation

Avant de commencer ce tutoriel, vous aurez besoin de ce qui suit :

  • alexyoung/dailyjs-backbone-tutorial en version 0c6de32 ;
  • la clé de l'API de la partie 2 ;
  • l'ID client de la partie 2 ;
  • la mise à jour de app/js/config.js avec vos clés.

Pour consulter la source, exécutez les commandes suivantes (ou utilisez un outil approprié pour Git GUI) :

 
Sélectionnez
git clone git@github.com:alexyoung/dailyjs-backbone-tutorial.git
cd dailyjs-backbone-tutorial
git reset --hard 0c6de32

II. Routage

Jusqu'à maintenant nous avons mis en place une gestion générale de listes et de tâches, mais travailler avec plusieurs listes est délicat parce que les listes ne peuvent pas être référencées par une URL. Si la page est rechargée, la liste actuelle n'est pas restituée et les listes ne peuvent pas être mises en favoris.

Heureusement, Backbone fournit une solution pour ces deux problèmes : Backbone.Router. Cela fournit une couche autour des Hash URLs (qui contiennent des #) et une fonctionnalité history.pushState.

III. Quand utiliser des Hash URLs ?

J'avoue que je trouve que les Hash URLs ne sont pas pratiques, et ce sentiment semble avoir été renforcé par l'utilisation qu'en a fait Twitter. Cependant, il y a un bon côté à ces URLs : elles nécessitent moins de travail pour les construire et sont rétrocompatibles avec les navigateurs plus anciens.

L'utilisation de history.pushState signifie que le navigateur peut afficher toutes les URLs que vous voulez. Au lieu de /#lists/id, la version plus jolie /lists/id peut être affichée. Toutefois, sans une configuration appropriée côté serveur, visiter /lists/id avant le chargement de l'application principale échoue alors que la version « hash » de l'URL fonctionne.

Si vous faites une page unique assez simple et autonome, évitez d'utiliser pushState et utilisez plutôt les Hash URLs.

Quoi qu'il en soit, Backbone rend facile le fait de basculer entre les deux options. Les Hash URLs sont la valeur par défaut, et history.pushState sera utilisé lorsqu'il est spécifié avec Backbone.history.start ({pushState : true}).

IV. Les fichiers de routage

C'est généralement une bonne idée de garder le routage séparé du reste de l'application. Créez un nouveau fichier appelé app/js/routes.js et ajoutez un extend au routeur de Backbone :

 
Sélectionnez
define(function() {
  return Backbone.Router.extend({
    routes: {
      'lists/:id': 'openList'
    },

    initialize: function() {
    },

    openList: function(id) {
    }
  });
});

Ce code définit le routage. Cette application n'a besoin que d'un chemin pour l'instant : lists/:id. La partie :id est un paramètre qui sera extrait par Backbone.Router et envoyé en tant qu'argument à openList.

V. Chargement du routage

La classe centralisée App est un bon endroit pour charger le routage et le configurer. Ouvrez app/js/app.js et modifiez-le define afin d'inclure les 'routes' :

 
Sélectionnez
define([
  'gapi'
, 'routes'
, 'views/app'
, 'views/auth'
, 'views/lists/menu'
, 'collections/tasklists'
, 'collections/tasks'
],

function(ApiManager, Routes, AppView, AuthView, ListMenuView, TaskLists, Tasks) {
  var App = function() {
    this.routes = new Routes();

Maintenant, déplacez-vous vers la ligne 35 où il y a une fonction callback qui s'exécute lorsque le gestionnaire de l'API est prêt. C'est lorsque Backbone.history.start doit être appelée :

 
Sélectionnez
App.prototype = {
  views: {},
  collections: {},
  connectGapi: function() {
    var self = this;
    this.apiManager = new ApiManager(this);
    this.apiManager.on('ready', function() {
      self.collections.lists.fetch({ data: { userId: '@me' }, success: function(collection, res, req) {
        self.views.listMenu.render();
        Backbone.history.start();
      }});
    });
  }
};

Techniquement, on peut appeler cela, quand le routage est chargé, mais le gestionnaire d'itinéraire openList nécessite que certaines listes existent. Il est donc préférable de la charger lorsque l'API est prête.

Le but de la méthode start est de commencer à surveiller les événements hashchange. Chaque fois que l'URL de la barre d'adresses du navigateur change, le routeur sera invoqué.

VI. Ouverture des listes à l'aide d'événements

Pour écrire des applications Backbone découplées, vous devez penser en terme de la pile complète Backbone : modèles, collections et vues. Lorsqu'une personne visite une URL faisant partie des favoris qui fait référence à un modèle spécifique, le gestionnaire d'itinéraire devrait être en mesure de trouver le modèle associé.

La documentation Backbone est très claire sur la puissance des événements personnalisés, et c'est d'ailleurs ainsi que openList dans app/js/routes.js devrait fonctionner :

 
Sélectionnez
openList: function(id) {
  if (bTask.collections.lists && bTask.collections.lists.length) {
    var list = bTask.collections.lists.get(id);
    if (list) {
      list.trigger('select');
    } else {
      console.error('List not found:', id);
    }
  }
}

J'ai été strict sur la vérification de l'existence de la collection de listes et même lors de l'extraction d'un modèle de liste donnée de la collection. La principale raison pour cela est d'être en mesure d'afficher des messages d'erreurs raisonnables. Mais pour l'instant, il y a juste un console.error pour aider à dépister les problèmes de chargement des données.

La dernière pièce du puzzle est le code de la vue qui a la responsabilité de l'affichage des listes. Ouvrez le fichier app/js/views/lists/menuitem.js et apportez les modifications suivantes :

  • ajoutez this.model.on('select', this.open, this); à la méthode initialize ;
  • ajoutez bTask.routes.navigate('lists/' + this.model.get('id')); à la méthode render.

La première ligne lie l'événement personnalisé select à partir de la vue du modèle (qui représente la liste). La deuxième ligne provoque le changement de l'URL du navigateur.

VII. Résumé

Combiner les événements et le routage est le secret pour écrire des applications Backbone découplées. Il peut être difficile de le faire correctement. Il y a certainement souvent des solutions plus rapides qui peuvent se traduire par du code « spaghetti ». Pour éviter des situations comme celle-ci, pensez-y en matière de modèles, de collections, de vues et de relations.

Le code source de ce tutoriel se trouve ici : alexyoung / dailyjs-backbone-tutorial en version 85c358.

VIII. Remerciements

Cet article a été publié avec l'aimable autorisation de Alex Young. L'article original peut être lu sur le site DailyJSDailyJS : Backbone.js Tutorial: RoutesBackbone.js Tutorial: Routes.

Je remercie également zoom61 pour sa relecture attentive et assidue.