2012-07-31 51 views
1

我正在构建一个骨干应用,结合https://github.com/addyosmani/backbone-aura/的模块化和外观/中介发布/子模式在模块之间发送消息,以保持干净的代码库。使用中介发布/发布模式时路由骨干应用

在光环整个应用程序例如为Grepping Router,我发现仅为了描述的路由器是自己的模块的一部分的理想使用的自述文件:“在Backbone.js的术语,窗口小部件是由模型,视图,集合和路由器以及小部件渲染所需的任何模板。“

所以我尝试了一些解决方案,以实现可扩展的路由系统(可升级的意义模块可以指定自己的子路径),包括接受消息set-route设置路由听route消息的路由器模块和模块。我还使用了每个模块的子路由器。问题似乎是,在初始页面加载时,由于消息的“异步”特性,路由及其回调可能无法在全局路由器解析URL时定义。你可以想象我可能需要在启动路由器模块之前对所有消息进行排队。

我想实现一些干净的东西,这是有道理的。我也在考虑首先潜在地解析所有小部件的所有路由,然后实例化路由器,这使得路由器模块成为特例,因此不应该是模块的一部分。

路由器应该是一个使用消息的模块吗?或者它应该是扩展模块,还是模块有权访问的全局体系结构的更高阶部分?

我知道这是一个加载的问题,在此先感谢您的帮助!

回答

1

关于这个问题一直存在很多争议,我认为很多是源自我认为对Router正式称为Controller的混淆。到去年年底我开始使用Backbone时,已经做出了改变,但我相信很多人已经在作为控制器的路由器周围构建了应用程序。我从来没有同意这一点。对我来说 - 早在Backbone被创建之前,依靠建立类似于Backbone的专有MVC引擎的经验 - 路由器只是一个历史管理器组件。

因此,为了解决在决定如何最好地实现路由器,考虑几件事情您的具体问题:

  1. 首先,路由器不是一个应用程序的必要组成部分。您可以在没有路由器的情况下继续浏览应用程序的各种页面或屏幕。
  2. 路由器不是一个控制器,其主要功能是管理历史。尽管您可以在路由器中嵌入应用程序业务逻辑,但我总是发现,这会混淆路由器真正做的事情。
  3. 通过使路由器成为应用程序的一个组件,可以创建更好的问题分离,并且可以有更有效的pub/sub排列类型。

下面是一个路由器模块我在我的应用程序使用下面的调解员,发布/订阅模式代码:

/** 
* 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; 
     } 
    }); 
}); 

然后当我实例化的组件,我将它传递一张地图,这样我的控制器知道什么模块导航到:

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

我这个发现的最重要的事情是,它使得代码简单好用,并让我专注于业务逻辑在我的控制器。