Используя Магистраль, возможно ли получить имя текущего маршрута? Я знаю, как привязываться к событиям изменения маршрута, но я хотел бы иметь возможность определять текущий маршрут в другое время, между изменениями.
Backbone.js: получить текущий маршрут
Ответ 1
Если вы создали экземпляр Router в своем приложении, следующая строка возвращает текущий фрагмент:
Backbone.history.getFragment();
" [...] История служит глобальным маршрутизатором (для каждого кадра) для обработки событий hashchange или pushState, соответствия соответствующего маршрута и срабатывания обратных вызовов. Вам никогда не придется создавать один из них самостоятельно - вы должны использовать ссылку на Backbone.history, которая будет создана для вас автоматически, если вы используете Маршрутизаторы с маршрутами. [...] "
Если вам нужно имя функции, связанной с этим фрагментом, вы можете сделать что-то вроде этого в области вашего маршрутизатора:
alert( this.routes[Backbone.history.getFragment()] );
Или вроде этого со стороны вашего маршрутизатора:
alert( myRouter.routes[Backbone.history.getFragment()] );
Ответ 2
Ответ Роберт интересен, но, к сожалению, он будет работать только в том случае, если хеш точно соответствует определению маршрута. Если у вас, например, есть маршрут для user(/:uid)
, он не будет соответствовать, если Backbone.history.fragment
является либо "user"
, либо "user/1"
(оба являются двумя наиболее очевидными вариантами использования для такого маршрута). Другими словами, он найдет только соответствующее имя обратного вызова, если хеш будет точно "user(/:uid)"
(крайне маловероятно).
Так как мне нужна эта функциональность, я расширил Backbone.Router
с помощью функции current
, которая повторно использует код, используемый для использования объекта History и Router, для соответствия текущему фрагменту с определенными маршрутами для запуска соответствующего обратного вызова.
Для моего варианта использования он принимает необязательный параметр route
, который, если он установлен на что-либо правдиво, вернет соответствующее имя функции, определенное для маршрута. В противном случае он вернет текущий хэш-фрагмент из Backbone.history.fragment
.
Вы можете добавить код в существующий Extend, где вы инициализируете и настраиваете маршрутизатор Backbone.
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 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'
Я уверен, что некоторые улучшения могут быть сделаны, но это хороший способ, чтобы вы начали. Кроме того, легко создать эту функциональность без расширения маршрута-объекта. Я сделал это, потому что это был самый удобный способ для моей настройки.
Я еще не тестировал это полностью, поэтому, пожалуйста, дайте мне знать, если что-то идет на юг.
ОБНОВЛЕНИЕ 04/25/2013
Я внес некоторые изменения в функцию, поэтому вместо того, чтобы возвращать либо имя хеша, либо обратный вызов маршрута, я возвращаю объект с фрагментом, параметрами и маршрутом, чтобы вы могли получить доступ ко всем данным с текущего маршрута, как и из маршрут-событие.
Вы можете увидеть изменения ниже:
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
};
}
Смотрите предыдущий код для дальнейших комментариев и объяснений, они выглядят в основном одинаковыми.
Ответ 3
Чтобы получить маршрут вызова (или URL) из обработчика вызываемого маршрута, вы можете получить его, установив
Backbone.history.location.href ... the full url Backbone.history.location.search ... query string starting from ?
Я попал сюда в поисках этого ответа, поэтому, я думаю, я должен оставить то, что нашел.
Ответ 4
Если вы используете корневую настройку для маршрутизатора, вы также можете включить его для получения "реального" фрагмента.
(Backbone.history.options.root || "") + "/" + Backbone.history.fragment
Ответ 5
Вот немного более подробный (или, в зависимости от вашего вкуса, более читаемый) вариант Саймон ответ:
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
};
}
}
Ответ 6
Если вы посмотрите на источник для Router
, вы увидите, что когда маршрутизатор запускает событие, заявляя, что что-то меняется, он передает имя с именем "route: name".
http://documentcloud.github.com/backbone/docs/backbone.html#section-84
Вы всегда можете подключить событие "маршрут" на маршрутизаторе и сохранить его для получения текущего маршрута.