template - Backbone.js: obtener la ruta actual
backbonejs github (6)
Usando Backbone, ¿es posible para mí obtener el nombre de la ruta actual? Sé cómo enlazar eventos de cambio de ruta, pero me gustaría poder determinar la ruta actual en otros momentos, entre cambios.
Aquí hay un poco más detallado (o, dependiendo de tu gusto, más fácil de leer) versión de la respuesta de Simon :
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
};
}
}
Para obtener la ruta de llamada (o url) del manejador de ruta llamado, puede obtenerlo marcando
Backbone.history.location.href ... the full url Backbone.history.location.search ... query string starting from ?
Llegué aquí en la búsqueda de esta respuesta, así que supongo que debería dejar lo que encontré.
Si ha creado una instancia de un enrutador en su aplicación, la siguiente línea devuelve el fragmento actual:
Backbone.history.getFragment();
De la documentación de Backbone.js :
"[...] El historial sirve como un enrutador global (por cuadro) para manejar eventos hashchange o pushState, hacer coincidir la ruta apropiada y desencadenar devoluciones de llamada. No debe tener que crear uno de estos usted mismo - debe usar la referencia a Backbone.history que se creará para usted automáticamente si utiliza Routers con rutas. [...] "
Si necesita el nombre de la función vinculada a ese fragmento, puede hacer algo como esto dentro del alcance de su enrutador:
alert( this.routes[Backbone.history.getFragment()] );
O como esto desde fuera de tu enrutador:
alert( myRouter.routes[Backbone.history.getFragment()] );
Si mira la fuente del Router
, verá que cuando el enrutador activa el evento diciendo que algo cambia, pasa el nombre con "ruta: nombre".
http://documentcloud.github.com/backbone/docs/backbone.html#section-84
Siempre puede conectar el evento de "ruta" en el enrutador y almacenarlo para obtener la ruta actual.
Si usa la configuración raíz para el enrutador, también puede incluirlo para obtener el fragmento ''real''.
(Backbone.history.options.root || "") + "/" + Backbone.history.fragment
La respuesta de Robert es interesante, pero lamentablemente solo funcionará si el hash es exactamente como se define en la ruta. Si, por ejemplo, tiene una ruta para el user(/:uid)
, no coincidirá si el Backbone.history.fragment
es "user"
o "user/1"
(ambos son los dos casos de uso más obvios para tal ruta). En otras palabras, solo encontrará el nombre de devolución de llamada apropiado si el hash es exactamente "user(/:uid)"
(muy improbable).
Como necesitaba esta funcionalidad, extendí Backbone.Router
Rute con una función current
que reutiliza parte del código que usan el objeto History y Router para hacer coincidir el fragmento actual con las Rutas definidas para activar la devolución de llamada apropiada. Para mi caso de uso, toma la route
parámetro opcional, que si se establece en algo veraz devolverá el nombre de función correspondiente definido para la ruta. De lo contrario, devolverá el fragmento hash actual de Backbone.History.fragment
.
Puede agregar el código a su Extend existente donde inicializa y configura el enrutador 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''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''
Estoy seguro de que se pueden hacer algunas mejoras, pero esta es una buena manera de comenzar. Además, es fácil crear esta funcionalidad sin extender el objeto Route. Hice esto porque era la forma más conveniente para mi configuración.
Todavía no lo he probado completamente, así que avíseme si algo va hacia el sur.
ACTUALIZACIÓN 25/04/2013
Hice algunos cambios a la función, así que en lugar de devolver el hash o el nombre de devolución de ruta, devuelvo un objeto con fragmento, params y ruta para que pueda acceder a todos los datos de la ruta actual, al igual que lo haría desde la ruta: evento.
Puedes ver los cambios a continuación:
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
};
}
Consulte el código anterior para obtener más comentarios y explicaciones, se ven más o menos iguales.