Présentation de Backbone.js

Backbone.js logo

Présentation

Introduction

Backbone.js est un framework JavaScript basé sur la librairie Underscore.JS. Il permet de structurer une application web, non plus comme une suite d’instructions jQuery, mais comme un assemblage de vues autonomes les unes des autres.
Son but est de poser des bases fortes pour développer des applications riches, sans pour autant imposer une structure applicative.

Il se veut non-contraignant par rapport à ses rivaux, ce qui lui coûte d’être présenté souvent comme moins complet. Son point fort est d’être facilement utilisable avec d’autres librairies ou frameworks.

Ses dépendances

Backbone.js est basé sur la librairie Underscore.JS. Cette dernière propose des fonctionnalités de manipulation d’objets, de collections et de tableaux assez poussées. Comme toute librairie populaire, elle se veut cross-browser et par héritage, Backbone.JS l’est aussi.
Underscore.JS
Pour tout ce qui est manipulation DOM, plutôt que réinventer la roue, l’équipe en charge de Backbone.JS a décidé de sous traiter cette tâche à jQuery. Il est possible de remplacer jQuery, par exemple avec Zepto, du moment qu’elle respecte l’api jQuery-compatible.
jQuery

Les composants

Backbone.JS fournit des composants logiciels pouvant être utilisés librement, que ce soit avec les autres composants Backbone.JS ou avec une autre librairie. Les trois plus importants sont le Model, la Collection et la View.

On parlera également de deux composants moins importants mais qui fournissent des fonctionnalités très intéressantes : Router et Sync.

L’utilisation de chaque composant se fait par extension de la classe. Lors de l’extension, il est possible de réimplémenter les méthodes ou de redéfinir les attributs et ainsi paramétrer l’objet pour que son comportement corresponde à nos attentes. La documentation est très bien fournie sur ce point qui se trouve être, à mon sens, un des points forts de Backbone.JS.

var ExtendClass = Backbone.Model.extend({
  initialize: function() { ... }
});

Les données

Backbone.Model

La classe Backbone.Model est utilisée pour gérer du contenu sous la forme d’un objet JavaScript en l’encapsulant et en proposant des méthodes accesseurs.

var Article = Backbone.Model.extend({});

var article = new Article({
  title: 'New Article'
});

article.get('title'); // New Article

article.set('title', 'New title');

article.get('title'); // New title

Testez ce code en ligne sur jsfiddle

Backbone.Collection

La classe Backbone.Collection permet de manipuler des collections de Model. On retrouve les méthodes habituelles : push, pop, shift, unshift, add, remove, get, sort ou encore length. On retrouve également les fonctions provenant de Underscore.JS.

var Article = Backbone.Model.extend({});

var Articles = Backbone.Collection.extend({
  model : Article
});

var articles = new Articles([{
  title: 'Article 1'
},{
  title: 'Article 2'
},{
  title: 'Article 3'
}]);

articles.push(articles.shift());

articles.models = articles.shuffle();

Testez ce code en ligne sur jsfiddle

Backbone.Sync

Concrètement, jusque là, nous avons vu comment manipuler des données. Mais pourquoi s’embêter avec  alors que nous pourrions le faire plus simplement? C’est Sync qui va vous apporter la réponse.

Sync est le composant permettant de synchroniser les objets à travers une API du type RESTful JSON. Pour cela, il suffit de lier les objets Model et Collection à une ressource grâce à l’attribut url.

var urlModel = 'http://ippon.fr/articles/1';
var urlCollection = 'http://ippon.fr/articles';

var Article = Backbone.Model.extend({
  url: urlModel;
});

var Articles = Backbone.Collection.extend({
  model: Article,
  url: urlCollection
});

Testez ce code en ligne sur jsfiddle

La vue

Comme je l’ai signalé au début de l’article, Backbone.JS a pour but de poser les bases du développement MVC en JavaScript. Backbone.View. C’est pourquoi, pour toutes les manipulations DOM, on retrouve le plugin jQuery qui est de loin, le mieux armé pour ces opérations.

Backbone.View

Chaque objet Backbone.View est lié à un nœud DOM (el) et pourra le générer à nouveau, à n’importe quel moment. Le but est alors de découper le document en une multitude de vues que l’on pourra regénérer à souhait et individuellement.

var View = Backbone.View.extend({
  render: function() {
    $(this.el).html(new Date().toLocaleTimeString());
    return $(this.el);
  }
});

var view = new View();

Ces deux techniques ont leurs avantages et leurs inconvénients. Pour ma part, je préconise la deuxième solution.

Les événements

Backbone.View permet de gérer les événements d’un nœud assez simplement. Munissez-vous de l’action souhaitée et du sélecteur, et le tour est joué.

var View = Backbone.View.extend({
  render: function() {
    $(this.el).html(this.template);
    return $(this.el);
  },
  events: {
    'click #button1' : 'onClickButton1',
    'hover .button2' : 'onHoverButton2'
  },
  onClickButton1 : function() {
    alert('button1');
  },
  onHoverButton2: function() {
    alert('button2');
  }
});

Testez en ligne sur jsfiddle

Exemple complet

Maintenant que vous connaissez les grandes lignes de Backbone.JS, il est temps de vous fournir un exemple utilisant tous les composants vus précédemment.
Libre à vous de vous amuser à rajouter des fonctionnalités.

Testez en ligne sur jsfiddle

Pour aller plus loin

Gestion des routes

Maintenant que nous pouvons réaliser des pages web composées de Backbone.View, peut-on aussi facilement gérer les différents états d’une page et y lier une URL ?

Si j’évoque le sujet, il est évident que la réponse est positive. Backbone.Router permet de mettre en place cette démarche. Une URI est composée d’un nom de domaine (tatami.ippon.fr) et d’une ressource (/tatami/). Il est possible de rajouter à la suite une ancre délimitée par une dièse (#/timeline). C’est cette ancre que Backbone.Router utilise pour déterminer quel est l’état de la page demandée.

Pour illustrer ces propos, une fois authentifié sur la page d’accueil de Tatami, chaque onglet représente un état de la page. Il en existe 5 actuellement :

  • “#/timeline”, la page avec l’onglet “Status” affiché
  • “#/favoris”, la page avec l’onglet “Favoris” affiché
  • “#/tags”, la page avec l’onglet “Tags” affiché
  • “#/search”, la page avec l’onglet “Recherche” affiché
  • “#/daily”, la page avec l’onglet “Status du jour” affiché

Source du router home de Tatami

Asynchronous Module Definition API

Il est possible d’utiliser Backbone.JS avec un AMD Loader comme RequireJS ou Curl. Ni Backbone.JS, ni Underscore ne supportent officiellement AMD. Toutefois, il est possible d’utiliser un fork implémentant de cette API.

On trouve sur Github des projets templates (boilerplate) qui facilitent la mise en place d’un environnement couplant RequireJS et Backbone. En voici deux parmi tant d’autres :

Plugins

Backbone.JS se veut léger : il ne fournit que des composants essentiels. Un des gros manquements de Backbone.JS par rapport à ses concurrents est l’absence de la fonctionnalité de DataBinding. Mais qu’à cela ne tienne, de nombreux plugins sont présents en libre accès sur GitHub, pour implémenter des fonctionnalités. Voici, quelques plugins que je trouve intéressants :

Conclusion

Je me suis occupé de la migration de Tatami vers une interface utilisant Backbone.JS, et son utilisation s’est révélée être très agréable et facilitée lorsqu’on le couple à une API RESTful JSON.

Vous pouvez accéder au code source de Tatami et voir comment Backbone.JS peut être utilisé dans un projet.

Par rapport à l’existant post-Backbone, la nouvelle version est plus claire, plus structurée. Elle respecte également la séparation modèle/vue et est modulaire, facilitant ainsi sa maintenance.

Pour aller plus loin, je vous conseille de lire sur cet article qui explique les différentes étapes qui permettent de passer d’une application full-jQuery à une application utilisant Backbone.JS.

TwitterFacebookGoogle+LinkedIn
  • François Le Droff

    Avec require v2 tu peux wrapper les libs non amd par l’ajout d’une annotation.