2012-07-31 3 views
1

Je construis une application en backbone combinant les modèles modulaires et facade/médiateur pub/sub de https://github.com/addyosmani/backbone-aura/ pour envoyer des messages entre les modules afin de garder une base de code propre. Dans l'exemple complet de l'aura, je n'ai trouvé que le fichier readme décrivant l'utilisation idéale des routeurs faisant partie des modules eux-mêmes: "Dans les termes de Backbone.js, les widgets sont composés de Models, Views, Collections et Les routeurs ainsi que tous les modèles nécessaires au rendu du widget. "routage applications backbone lors de l'utilisation mediator pub/sous modèles

donc j'ai essayé un certain nombre de solutions à mettre en œuvre un système de routage extensible (modules de sens évolutifs peuvent spécifier leurs propres SubRoutes), comprenant un module de routeur qui accepte un message set-route pour définir l'itinéraire, et des modules qui écoutent le message route. J'ai également utilisé un sous-routeur par module. Le problème semble que sur les chargements de page initiaux, en raison de la nature «asynchrone» de la messagerie, les routes et leurs rappels peuvent ne pas être définis au moment où le routeur global analyse l'URL. Vous pouvez imaginer que j'ai peut-être besoin de mettre en file d'attente tous les messages avant de démarrer le module routeur. Je veux mettre en œuvre quelque chose de propre et cela a du sens. Je pensais aussi à potentiellement analyser d'abord toutes les routes de tous les widgets, puis à instancier le routeur, ce qui fait du module routeur un cas particulier, et ne devrait donc pas faire partie des modules.

Le routeur doit-il être un module qui utilise des messages, ou doit-il s'agir d'une extension, ou d'un élément d'ordre supérieur de l'architecture global auquel les modules ont accès?

Je sais que c'est une question chargée, merci d'avance pour toute aide!

Répondre

1

Il y a eu beaucoup de discussions sur ce problème, et je pense que beaucoup de cela découlait de ce que je pense être la confusion sur Router officiellement appelé Controller. Au moment où j'ai commencé à utiliser Backbone à la fin de l'année dernière, le changement était déjà fait, mais je crois que beaucoup de gens avaient déjà construit des applications autour du routeur en tant que contrôleur. Je n'ai jamais été d'accord avec ça. Pour moi - s'appuyant sur l'expérience d'avoir construit un moteur MVC propriétaire similaire à Backbone bien avant la création de Backbone - un routeur était simplement un composant de gestionnaire d'historique.

Donc, pour résoudre votre problème particulier sur la meilleure façon de décider de mettre en œuvre un routeur, prendre en considération un certain nombre de choses:

  1. Tout d'abord, un routeur est pas un élément nécessaire d'une application. Vous pouvez faire sans un routeur et toujours naviguer vers les différentes pages ou écrans de l'application.
  2. Un routeur n'est pas un contrôleur car sa fonction principale est de gérer l'historique. Bien que vous puissiez intégrer la logique métier d'une application dans un routeur, j'ai toujours trouvé que cela brouille les pistes de ce qu'un routeur fait vraiment. En faisant d'un routeur un composant d'une application, vous créez une meilleure séparation des préoccupations, et vous pouvez avoir un type d'arrangement pub/sub beaucoup plus efficace.

est le code pour un module de routeur J'utilise ci-dessous dans mes applications qui suit le médiateur, pub/sous modèles:

/** 
* The idea behind this component is simply to relegate Backbone.Router to 
* doing what it does best: History Management. All it is responsible for 
* is two things: 
* 
* 1. Update the URL if router.navigate is invoked 
* 2. Trigger a routeChanged event if the URL was updated either by a bookmark or 
* typed in by a user. 
*/ 
define(function() { 
    return Backbone.Router.extend({ 
     initialize : function (map) { 
      this._reversedMap = this.reverseModuleMap(map); 
     }, 
     routes:{ 
      '*actions':'notify' 
     }, 
     notify:function (actions) { 
      var args = arguments; 
      this.trigger("routeChanged", {command:actions}); 
     }, 
     /** 
     * Override Backbone.Router.navigate. Default is to pass a router fragment, but for 
     * our uses, we'll translate the "route" into a module mapping so that the controller 
     * will know which module to display. 
     * @param param 
     * @param options 
     */ 
     navigate:function (param, options) { 
      //console.log('navigate', param); 
      if(!param.suppressNavigate && param.actionCommand) { 
       Backbone.Router.prototype.navigate.call(this, this._reversedMap[param.actionCommand]); 
      } else if(!param.actionCommand) { 
       Backbone.Router.prototype.navigate.call(this, param, options); 
      } 
     }, 
     /** 
     * this function simply reverses the key and value of the "map" 
      * @param map 
     */ 
     reverseModuleMap:function (map) { 
      var newMap = {}; 
      _.each(map, function (value, key) { 
       newMap[value] = key; 
      }); 
      // reversed key and value 
      return newMap; 
     } 
    }); 
}); 

Puis, quand j'instancier le composant, je passe une carte afin que mon contrôleur sait ce module pour naviguer vers:

this._router = new Router({ 
    _default: 'moduleA', 
    sites : 'moduleA', 
    apps : 'moduleB' 
}); 
this._router.on('routeChanged', this.handleRouteChange, this); 

la chose la plus importante que j'ai trouvé c'est qu'il garde le beau code et simple, et me permet de vous concentrer sur la logique métier dans mes contrôleurs.