使用 Backbone,我可以获取当前路由的名称吗?我知道如何绑定到路由更改事件,但我希望能够在更改之间的其他时间确定当前路由。
如果您在应用程序中实例化了路由器,则以下行将返回当前片段:
Backbone.history.getFragment();
“ [...] History 充当全局路由器(每帧)来处理 hashchange 事件或 pushState,匹配适当的路由,并触发回调。您永远不必自己创建其中一个 - 您应该使用参考到 Backbone.history,如果您使用带有路由的路由器,它将自动为您创建。[...]"
如果您需要绑定到该片段的函数的名称,您可以在路由器的范围内进行类似的操作:
alert( this.routes[Backbone.history.getFragment()] );
或者像这样从您的路由器外部:
alert( myRouter.routes[Backbone.history.getFragment()] );
Robert's answer 很有趣,但遗憾的是,它只有在哈希与路由中定义的完全一致时才有效。例如,如果您有 user(/:uid)
的路由,如果 Backbone.history.fragment
是 "user"
或 "user/1"
(这两者都是此类路由的两个最明显的用例),则不会匹配。换句话说,它只会在哈希正好是 "user(/:uid)"
时找到适当的回调名称(极不可能)。
由于我需要此功能,我使用 current
函数扩展了 Backbone.Router
,该函数重用 History 和 Router 对象用于将当前片段与定义的路由匹配以触发适当的回调的一些代码。对于我的用例,它采用可选参数 route
,如果设置为任何真实值,将返回为路由定义的相应函数名称。否则它将返回来自 Backbone.History.fragment
的当前哈希片段。
您可以将代码添加到您现有的扩展中,您可以在其中初始化和设置主干路由器。
var Router = new Backbone.Router.extend({
// Pretty basic stuff
routes : {
"home" : "home",
"user(:/uid)" : "user",
"test" : "completelyDifferent"
},
home : function() {
// Home route
},
user : function(uid) {
// User route
},
// Gets the current route callback function name
// or current hash fragment
current : function(route){
if(route && Backbone.History.started) {
var Router = this,
// Get current fragment from Backbone.History
fragment = Backbone.history.fragment,
// Get current object of routes and convert to array-pairs
routes = _.pairs(Router.routes);
// Loop through array pairs and return
// array on first truthful match.
var matched = _.find(routes, function(handler) {
var route = handler[0];
// Convert the route to RegExp using the
// Backbone Router's internal convert
// function (if it already isn't a RegExp)
route = _.isRegExp(route) ? route : Router._routeToRegExp(route);
// Test the regexp against the current fragment
return route.test(fragment);
});
// Returns callback name or false if
// no matches are found
return matched ? matched[1] : false;
} else {
// Just return current hash fragment in History
return Backbone.history.fragment
}
}
});
// Example uses:
// Location: /home
// console.log(Router.current()) // Outputs 'home'
// Location: /user/1
// console.log(Router.current(true)) // Outputs 'user'
// Location: /user/2
// console.log(Router.current()) // Outputs 'user/2'
// Location: /test
// console.log(Router.current(true)) // Outputs 'completelyDifferent'
我确信可以进行一些改进,但这是让您入门的好方法。此外,无需扩展 Route 对象即可轻松创建此功能。我这样做是因为它是我设置的最方便的方式。
我还没有完全测试这个,所以如果有任何事情发生,请告诉我。
2013 年 4 月 25 日更新
我对函数做了一些更改,因此我没有返回哈希或路由回调名称,而是返回一个带有片段、参数和路由的对象,这样您就可以从当前路由访问所有数据,就像您从路由访问一样-事件。
您可以看到以下更改:
current : function() {
var Router = this,
fragment = Backbone.history.fragment,
routes = _.pairs(Router.routes),
route = null, params = null, matched;
matched = _.find(routes, function(handler) {
route = _.isRegExp(handler[0]) ? handler[0] : Router._routeToRegExp(handler[0]);
return route.test(fragment);
});
if(matched) {
// NEW: Extracts the params using the internal
// function _extractParameters
params = Router._extractParameters(route, fragment);
route = matched[1];
}
return {
route : route,
fragment : fragment,
params : params
};
}
有关进一步的评论和解释,请参阅前面的代码,它们看起来几乎相同。
_.find
函数的第三个参数(设置上下文)设置为 this
,从而消除对 Router
变量的需要(@DanAbramov 已经这样做了)。
Marionette.AppRouter
,请使用上述功能扩展您的路由器,但用 Router.appRoutes
替换 Router.routes
。
要从被调用的路由处理程序中获取调用路由(或 url),您可以通过检查来获取它
Backbone.history.location.href ... the full url Backbone.history.location.search ... query string starting from ?
我来到这里是为了寻找这个答案,所以我想我应该留下我找到的东西。
如果您使用路由器的根设置,您还可以包含它以获取“真实”片段。
(Backbone.history.options.root || "") + "/" + Backbone.history.fragment
这是一个稍微更详细(或者,根据您的口味,更易读)的 Simon's answer 版本:
current: function () {
var fragment = Backbone.history.fragment,
routes = _.pairs(this.routes),
route,
name,
found;
found = _.find(routes, function (namedRoute) {
route = namedRoute[0];
name = namedRoute[1];
if (!_.isRegExp(route)) {
route = this._routeToRegExp(route);
}
return route.test(fragment);
}, this);
if (found) {
return {
name: name,
params: this._extractParameters(route, fragment),
fragment: fragment
};
}
}
如果您查看 Router
的源代码,您会发现当路由器触发表明某事发生变化的事件时,它会将名称与它一起作为“route:name”传递。
http://documentcloud.github.com/backbone/docs/backbone.html#section-84
您可以随时在路由器上挂钩“路由”事件并将其存储以获取当前路由。
trigger
不是 true
(推荐和默认),您将不会收到 route
事件。
router = new Backbone.Router.extend({
routes: { "stuff/:id" : "stuff" },
stuff: function(id) {}
});
router.on('route', function(route) {
this.current = route;
});
现在,如果您导航到 /stuff/1
,router.current 将是“东西”
不定期副业成功案例分享
Backbone.history.getFragment()
,因为Backbone.history.fragment
是私有的隐藏属性。