我最近的一个项目需要这个,我计划在某个时候将这个代码作为开源发布,但你可以这样做:
创建一个全局路由器来处理所有路由:
App.GlobalRouter = Backbone.Router.extend({
initialize: function(){
this._routes = {};
},
registerRoute: function(route, rootRoute){
var rootName;
if(rootRoute) {
route = rootRoute + '/' + route;
rootName = this.registerRoute(rootRoute);
}
if(!_.isRegExp(route))
route = this._routeToRegExp(route);
var name = this._routes[route] ? this._routes[route] : _.uniqueId('r');
this._routes[route] = name;
this.route(route, name, function(){});
if(rootName) {
this.on('route:'+name, function(){
var args = slice(arguments);
this.trigger.apply(this, ['route:' + rootName].concat(args));
}.bind(this));
}
return name;
}
});
然后创建一个:
App.globalRouter = new App.GlobalRouter();
然后创建一个修改过的路由器来扩展您的所有路由器:
App.Router = Backbone.Router.extend({
constructor: function (options){
options = options || {};
if(options.root) this.root = options.root;
this.globalRouter = App.globalRouter;
Backbone.Router.apply(this, [options]);
},
route: function(route, name, callback, root){
if(!App.globalRouter) return false;
// If callback is root param
if(callback && !_.isFunction(callback)) {
root = callback;
callback = null;
}
// If no name is callback param.
if(_.isFunction(name)) {
callback = name;
name = '';
}
if(!callback)
callback = this[name];
var router = this;
var roots = root || this.root;
if(roots && !_.isArray(roots)) roots = [roots];
if(roots) {
_.each(roots, function(root){
var globalName = App.globalRouter.registerRoute(route, root);
router.listenTo(App.globalRouter, 'route:'+globalName, function(){
var args = slice(arguments);
var callbackArgs = args.slice(callback && -callback.length || 0);
callback && callback.apply(router, callbackArgs);
router.trigger.apply(router, ['route:' + name].concat(callbackArgs));
router.trigger('route', name, callbackArgs);
});
});
} else {
var globalName = App.globalRouter.registerRoute(route);
router.listenTo(App.globalRouter, 'route:'+globalName, function(){
var args = slice(arguments);
var callbackArgs = args.slice(callback && -callback.length || 0);
callback && callback.apply(router, callbackArgs);
router.trigger.apply(router, ['route:'+name].concat(callbackArgs));
router.trigger('route', name, callbackArgs);
});
}
return this;
}
});
从这里您可以创建所需的尽可能多的路由器并将它们注册在同一路由上,您也可以创建一个具有要监听的路由路由的路由器,因此在您的情况下,您可能有 2 或 3 个路由器,这是一个示例你可以做什么:
var defaultRouter = App.Router.extend({
routes: {
'dashboard': 'showDashboard',
'game/:id': 'showGame'
},
showDashboard: function() {},
showGame: function(id) {},
});
var profilerRouter = App.Router.extend({
root: [
'dashboard',
'game/:id'
],
routes: {'profile', 'showProfile'},
showProfile: function(){//Show lightbox}
});
这将监听/dashboard
或/game/:id
调用defaultRouter
正在监听的函数。然后,如果/profile
url 位于任一路由的末尾,则将捕获它并showProfile
在 profileRouter 上运行该函数。
注意:我已经快速修改了我项目中的代码以更改一些名称/命名空间问题,因此您可能需要检查我没有遗漏任何内容,但代码应该是正确的,否则
更新示例:
- 如果用户导航到
/game/:id
它将调用defaultRouter > showGame
with param :id
。
- 如果用户导航到
/game/:id/profile
它将调用defaultRouter > showGame
with param :id
。它也会调用profileRouter > showProfile
但没有参数(即它不会从 /game/:id 根目录发送 :id )。