Utilizzando Backbone, è possibile ottenere il nome del percorso corrente? So come associare gli eventi di modifica del percorso, ma mi piacerebbe essere in grado di determinare il percorso corrente altre volte, tra le modifiche.
Utilizzando Backbone, è possibile ottenere il nome del percorso corrente? So come associare gli eventi di modifica del percorso, ma mi piacerebbe essere in grado di determinare il percorso corrente altre volte, tra le modifiche.
Risposte:
Se è stata creata un'istanza di un router nell'applicazione, la riga seguente restituisce il frammento corrente:
Backbone.history.getFragment();
Dalla documentazione Backbone.js :
"[...] La cronologia funge da router globale (per frame) per gestire gli eventi di hashchange o pushState, abbinare il percorso appropriato e attivare i callback. Non dovresti mai crearne uno tu stesso - dovresti usare il riferimento alla Backbone.history che verrà creata automaticamente se utilizzi router con route. [...] "
Se è necessario il nome della funzione associato a quel frammento, è possibile creare qualcosa del genere all'interno dell'ambito del router:
alert( this.routes[Backbone.history.getFragment()] );
O in questo modo dall'esterno del router:
alert( myRouter.routes[Backbone.history.getFragment()] );
Backbone.history.getFragment()
, perché Backbone.history.fragment
è una proprietà privata nascosta.
La risposta di Robert è interessante, ma purtroppo funzionerà solo se l'hash è esattamente come definito nella rotta. Ad esempio, se si dispone di un percorso, user(/:uid)
esso non verrà abbinato se Backbone.history.fragment
è uno "user"
o "user/1"
(entrambi sono i due casi d'uso più ovvi per tale percorso). In altre parole, troverà il nome di richiamata appropriato solo se l'hash è esattamente "user(/:uid)"
(altamente improbabile).
Dato che avevo bisogno di questa funzionalità, ho esteso Backbone.Router
con una funzione current
che riutilizza parte del codice utilizzato dall'oggetto History and Router per far corrispondere il frammento corrente ai percorsi definiti per attivare il callback appropriato. Nel mio caso d'uso, accetta il parametro opzionale route
, che se impostato su qualcosa di vero restituirà il nome della funzione corrispondente definito per il percorso. Altrimenti restituirà l'attuale frammento di hash da Backbone.History.fragment
.
È possibile aggiungere il codice all'estensione esistente in cui si inizializza e configura il router 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'
Sono sicuro che potrebbero essere apportati alcuni miglioramenti, ma questo è un buon modo per iniziare. Inoltre, è facile creare questa funzionalità senza estendere l'oggetto Route. L'ho fatto perché era il modo più conveniente per il mio set-up.
Non l'ho ancora testato completamente, quindi per favore fatemi sapere se qualcosa va a sud.
Ho apportato alcune modifiche alla funzione, quindi invece di restituire il nome di callback di hash o route, restituisco un oggetto con frammento, parametri e route in modo da poter accedere a tutti i dati dalla route corrente, proprio come faresti dalla route- evento.
Puoi vedere le modifiche qui sotto:
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
};
}
Vedi il codice precedente per ulteriori commenti e spiegazioni, sembrano quasi uguali.
_.find
funzione come this
, eliminando così la necessità della Router
variabile (lo ha già fatto @DanAbramov).
Marionette.AppRouter
, estendere il router con la funzione di cui sopra, ma sostituire Router.appRoutes
per Router.routes
.
Per ottenere la route di chiamata (o url) dal gestore di route chiamato, è possibile ottenerlo controllando
Backbone.history.location.href ... l'URL completo Backbone.history.location.search ... stringa di query a partire da?
Sono arrivato qui alla ricerca di questa risposta, quindi credo che dovrei lasciare ciò che ho trovato.
Se si utilizza l'impostazione di root per il router, è anche possibile includerla per ottenere il frammento "reale".
(Backbone.history.options.root || "") + "/" + Backbone.history.fragment
Ecco una versione un po ' più dettagliata (o, a seconda dei tuoi gusti, più leggibile) della risposta di 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
};
}
}
Se guardi l'origine per Router
, vedrai che quando il router attiva l'evento dicendo che qualcosa cambia, passa il nome con esso come "route: name".
http://documentcloud.github.com/backbone/docs/backbone.html#section-84
Puoi sempre agganciare l'evento "route" sul router e memorizzarlo per ottenere il percorso corrente.
route
evento se trigger
non lo è true
(consigliato e predefinito).