关于javascript:Backbone.js路由器匹配的可选参数

Backbone.js Router Matching Optional Parameters

我正在尝试创建可以匹配可选参数的Backbone 路由器。

考虑以下代码:

1
2
3
4
5
6
7
8
9
10
routes: {  
  '/jobs'                                     : 'jobs',
  '/jobs/p:page'                              : 'jobs',
  '/jobs/job/:job_id'                         : 'jobs',
  '/jobs/p:page/job/:job_id'                  : 'jobs'
}

jobs: function(page, job_id){
   // do stuff here ....
}

如果我导航至URL abc.com/#/jobs/p104/,则页面参数将为104。但是,如果导航至abc.com/#/jobs/job/93,则job_id参数未定义,但页面参数是93.

因此,Backbone 网的路由器基本上按顺序而不是按名称匹配路由哈希参数。

我知道解决方案是使用* splat并使用regex分割参数,但是我似乎无法使regex部分正常工作(我的regex非常生rust)。有人可以帮忙吗?

如果有比使用* splat更好的解决方案,请与他人分享吗?


拥有第二个功能将使您不再麻烦正则表达式,而是更轻松,更不易出错。为了使this.jobs正常工作,您可能必须将所有这些都绑定在一个初始化函数中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
routes: {  
  '/jobs'                                     : 'jobs',
  '/jobs/p:page'                              : 'jobs',
  '/jobs/job/:job_id'                         : 'jobsId',
  '/jobs/p:page/job/:job_id'                  : 'jobs'
},

jobs: function(page, job_id){
   // do stuff here ....
},

jobsId: function(page, job_id){
   this.jobs(undefined, job_id
}


尝试一下(单个正则表达式,适用于所有输入格式)

1
2
3
4
5
6
7
8
var re = /\\/jobs(?:\\/p(\\d+))?.*?(?:\\/(\\d+)|$)/;
var matches = 'abc.com/#/jobs/p104/4'.match(re);
var page=false;var job=false;
if (matches != null) {
    var page = matches[1] || false;
    var job = matches[2] || false;
};
alert("page:" + page +",job:" + job)

**首先匹配pNNN片段(如果存在),并使用带有点.的非贪婪量词,该量词可以吃掉任何.*?来逐个爬行字符串,从而使第二组(仅/ NNN)也将匹配(如果存在)。 (?: exp )是非捕获组,它们进行分组,但是它们没有"记住"任何内容。


如果您打算做很多这样的事情,您可能会瞥一眼这种整理整齐的模式。对于这些,以下正则表达式应该这样做:

1
2
/\\/jobs\\/p(\\d+)/              => /jobs/pXXX
/\\/jobs\\/p(\\d+)\\/job\\/(\\d+)/  => /jobs/pXXX/job/XXX

然后可以将String.match与检索到的splat一起使用以提取所涉及的url片段。使用字符串代替splat变量:

1
2
3
4
5
6
var matches = '/jobs/p18'.match(/\\/jobs\\/p(\\d+)/);
var page = matches[1];

var matches = '/jobs/p4/job/6/'.match(/\\/jobs\\/p(\\d+)\\/job\\/(\\d+)/);
var page = matches[1];
var job = matches[2];