通过Backbone路由处理视图选项

时间:2013-04-03 18:25:49

标签: backbone.js marionette

我已经开发了大约一年的大型Backbone Marionette应用程序。一直困扰的一件事是在路线中传递视图状态的选项。视图状态的选项示例包括页面上的活动选项卡,临时选定项或排序选项,这些选项需要是可链接的。

在更新到Backbone 0.9.9+之前,我发现处理这些情况的最佳方法是在路由末尾添加查询参数。我的路由器看起来像这样:

"/questions/:id/"         : "showQuestions"
"/questions/:id/?*params" : "showQuestionsWithFilters"

哪个匹配如下:

"/questions/1/?search=help&sort=name"

我发现的真正优势是路由器将根据url参数的存在匹配不同的路由。清除所有网址参数然后触发导航实际上会导致路由更改。

Backbone 0.9.2路由器不再识别url参数。在上面的示例中,无论是否存在url参数,都会触发“showQuestions”方法。这个GH问题(https://github.com/documentcloud/backbone/issues/891)的普遍共识和Backbone贡献者的意见似乎是url参数根本不应该在客户端使用,而是所有需要传递给视图的信息应存储在主网址路径(https://github.com/documentcloud/backbone/issues/2440)。

使用此方法的路由器可能类似于:

"/questions/:id/(search/:term)(sort/:type/)"

此方法的问题是需要将每个可选参数显式添加到路由器,并且必须相应地对所有参数进行排序,否则它们将不匹配。由于路由及其选项之间没有描述符,并且顺序由路由器确定,因此动态添加或编辑选项似乎不必要。

此时我处于保持现有网址结构并试图找到一种方法使其工作或迁移到后一种方法之间。在我向任何一个方向走得太远之前,我想知道是否对类似用例的最佳实践有其他意见。 你会推荐什么?

1 个答案:

答案 0 :(得分:2)

另一条叫做splat的路线。来自http://backbonejs.org/#Router

  

路由可以包含参数部分:param,它匹配单个URL   斜杠之间的组件;和splat部分* splat,可以匹配任何   URL组件的数量。

在我的应用中,我使用了一个必需的参数,然后是任意数量的可选“过滤器”:

var BrowseRouter = Marionette.AppRouter.extend({
  appRoutes: {
    'browse/:page(/*filters)': 'browse'
  }
});

然后使用由斜杠分隔的一系列键/值对格式化我的URL:#/browse/3/type:image/sort:date/count:24

在我的控制器中,我传递了两个参数:pagefilterspage是一个简单的值(“3”)。 filters是可选的,是一个较长的字符串,包含页面值之后的所有内容(“type:image / sort:date / count:2”)。

我有一个“爆炸”下划线mixin来获取该字符串并将其转换为对象。

_.mixin({
  /*
   * Take a formatted string (from the URL) and convert it into an object of
   * key/val pairs. If the val looks like an array, make it so.
   * _.explode("count:105/sort:date/type:image,video")
   * => { count: 105, sort: date, type: ['image','video']}
   */
  explode: function(str) {
    var result = {};
    if(!str){
        return result;
    }
    _.each(str.split('/'), function(element, index, list){
      if(element){
        var param = element.split(':');
        var key = param[0];
        var val = param[1];
        if (val.indexOf(",") !== -1) {
          val = val.split(',');
        }
        result[key] = val;
      }
    });
    return result;
  }
});