Con Backbone, ¿puedo obtener el nombre de la ruta actual? Sé cómo vincularme con los eventos de cambio de ruta, pero me gustaría poder determinar la ruta actual en otros momentos, entre cambios.
Con Backbone, ¿puedo obtener el nombre de la ruta actual? Sé cómo vincularme con los eventos de cambio de ruta, pero me gustaría poder determinar la ruta actual en otros momentos, entre cambios.
Respuestas:
Si ha instanciado 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 trama) para manejar eventos de cambio de hash o pushState, hacer coincidir la ruta apropiada y activar devoluciones de llamada. Nunca debería tener que crear uno de estos, debe usar la referencia a Backbone.history que se creará para usted automáticamente si utiliza enrutadores 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 así desde fuera de su enrutador:
alert( myRouter.routes[Backbone.history.getFragment()] );
Backbone.history.getFragment()
, porque Backbone.history.fragment
es una propiedad privada oculta.
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 user(/:uid)
, no coincidirá si Backbone.history.fragment
es uno "user"
o "user/1"
ambos (ambos son los dos casos de uso más obvios para dicha ruta). En otras palabras, solo encontrará el nombre de devolución de llamada apropiado si el hash es exactamente "user(/:uid)"
(muy poco probable).
Como necesitaba esta funcionalidad, extendí la función Backbone.Router
con una current
función que reutiliza parte del código que usan los objetos Historial y Enrutador para hacer coincidir el fragmento actual con las Rutas definidas para activar la devolución de llamada apropiada. Para mi caso de uso, toma el parámetro opcional route
, que si se establece en algo verdadero devolverá el nombre de la función correspondiente definida para la ruta. De lo contrario, devolverá el fragmento hash actual de Backbone.History.fragment
.
Puede agregar el código a su extensión 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 podrían hacer algunas mejoras, pero esta es una buena manera de comenzar. Además, es fácil crear esta funcionalidad sin extender el objeto Ruta. 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 mal.
Hice algunos cambios en la función, por lo que en lugar de devolver el nombre de devolución de llamada hash o ruta, devuelvo un objeto con fragmento, parámetros 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
};
}
Vea el código anterior para más comentarios y explicaciones, se ven casi iguales.
_.find
función como this
, eliminando así la necesidad de la Router
variable (@DanAbramov ya lo hizo).
Marionette.AppRouter
, ampliar su router con la función anterior, pero sustituto Router.appRoutes
para Router.routes
.
Para obtener la ruta de llamada (o url) del controlador de ruta llamado, puede obtenerla marcando
Backbone.history.location.href ... la url completa Backbone.history.location.search ... cadena de consulta a partir de?
Llegué aquí en busca de esta respuesta, así que supongo que debería dejar lo que he encontrado.
Si usa la configuración raíz para el enrutador, también puede incluirla para obtener el fragmento 'real'.
(Backbone.history.options.root || "") + "/" + Backbone.history.fragment
Aquí hay una versión un poco más detallada (o, según su gusto, más legible) 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
};
}
}
Si observa el origen del Router
, verá que cuando el enrutador activa el evento diciendo que algo cambia, pasa el nombre con él como "ruta: nombre".
http://documentcloud.github.com/backbone/docs/backbone.html#section-84
Siempre puede conectar el evento "ruta" en el enrutador y almacenarlo para obtener la ruta actual.
route
evento si trigger
no lo está true
(recomendado y predeterminado).