Могу ли я получить имя текущего маршрута, используя Backbone? Я знаю, как выполнить привязку к событиям изменения маршрута, но я хотел бы иметь возможность определять текущий маршрут в другое время, между изменениями.
backbone.js
Дрю Дара-Абрамс
источник
источник
Ответы:
Если вы создали экземпляр Router в своем приложении, следующая строка возвращает текущий фрагмент:
Из документации Backbone.js :
"[...] История служит глобальным маршрутизатором (для каждого кадра) для обработки событий hashchange или pushState, сопоставления с соответствующим маршрутом и запуска обратных вызовов. Вам никогда не придется создавать один из них самостоятельно - вы должны использовать ссылку в Backbone.history, который будет создан автоматически, если вы используете маршрутизаторы с маршрутами. [...] "
Если вам нужно имя функции, связанной с этим фрагментом, вы можете сделать что-то вроде этого внутри области видимости вашего маршрутизатора:
alert( this.routes[Backbone.history.getFragment()] );
Или вот так извне вашего роутера:
источник
Backbone.history.getFragment()
, потому чтоBackbone.history.fragment
это частная скрытая собственность.Ответ Роберта интересен, но, к сожалению, он будет работать только в том случае, если хеш будет точно таким, как определено в маршруте. Например, если у вас есть маршрут для
user(/:uid)
него, он не будет сопоставлен, еслиBackbone.history.fragment
будет либо,"user"
либо"user/1"
(оба являются двумя наиболее очевидными вариантами использования для такого маршрута). Другими словами, он найдет подходящее имя обратного вызова только в том случае, если хэш точный"user(/:uid)"
(очень маловероятно).Поскольку мне нужна была эта функциональность, я расширил ее
Backbone.Router
с помощьюcurrent
-функции, которая повторно использует часть кода, используемого объектом History и Router, для сопоставления текущего фрагмента с определенными маршрутами для запуска соответствующего обратного вызова. Для моего варианта использования он принимает необязательный параметрroute
, который, если задано что-либо правдивое, вернет соответствующее имя функции, определенное для маршрута. В противном случае он вернет текущий хеш-фрагмент изBackbone.History.fragment
.Вы можете добавить код в существующий Extend, где вы инициализируете и настраиваете Backbone router.
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. Я сделал это, потому что это был наиболее удобный способ для моей настройки.
Я еще не тестировал это полностью, поэтому, пожалуйста, дайте мне знать, если что-то пойдет не так.
ОБНОВЛЕНИЕ 25.04.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 }; }
См. Предыдущий код для дальнейших комментариев и объяснений, они в основном выглядят одинаково.
источник
_.find
функции какthis
, тем самым устраняя необходимость вRouter
переменной (@DanAbramov уже сделал это).Marionette.AppRouter
, расширить маршрутизатор с функцией выше, но заменаRouter.appRoutes
дляRouter.routes
.Чтобы получить маршрут вызова (или URL-адрес) от вызываемого обработчика маршрута, вы можете получить его, проверив
Я попал сюда в поисках этого ответа, поэтому, думаю, мне следует оставить то, что я нашел.
источник
Если вы используете корневую настройку для маршрутизатора, вы также можете включить ее, чтобы получить «настоящий» фрагмент.
(Backbone.history.options.root || "") + "/" + Backbone.history.fragment
источник
Вот чуть более многословным (или, в зависимости от вашего вкуса, более удобным для чтения) версии ответа Саймона :
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
Вы всегда можете подключить событие "route" к маршрутизатору и сохранить его, чтобы получить текущий маршрут.
источник
route
событие, еслиtrigger
его не будетtrue
(рекомендуется и по умолчанию).router = new Backbone.Router.extend({ routes: { "stuff/:id" : "stuff" }, stuff: function(id) {} }); router.on('route', function(route) { this.current = route; });
Теперь, если вы
/stuff/1
перейдете к , router.current будет "stuff"источник