Kann ich mit Backbone den Namen der aktuellen Route abrufen? Ich weiß, wie man sich an Routenänderungsereignisse bindet, möchte aber in der Lage sein, die aktuelle Route zu anderen Zeiten zwischen Änderungen zu bestimmen.
Kann ich mit Backbone den Namen der aktuellen Route abrufen? Ich weiß, wie man sich an Routenänderungsereignisse bindet, möchte aber in der Lage sein, die aktuelle Route zu anderen Zeiten zwischen Änderungen zu bestimmen.
Antworten:
Wenn Sie in Ihrer Anwendung einen Router instanziiert haben, gibt die folgende Zeile das aktuelle Fragment zurück:
Backbone.history.getFragment();
Aus der Dokumentation zu Backbone.js :
"[...] Der Verlauf dient als globaler Router (pro Frame), um Hash-Change-Ereignisse oder PushState zu verarbeiten, die entsprechende Route abzugleichen und Rückrufe auszulösen. Sie sollten niemals eine dieser Routen selbst erstellen müssen - Sie sollten die Referenz verwenden zu Backbone.history, die automatisch für Sie erstellt wird, wenn Sie Router mit Routen verwenden. [...] "
Wenn Sie den Namen der an dieses Fragment gebundenen Funktion benötigen, können Sie im Rahmen Ihres Routers Folgendes erstellen:
alert( this.routes[Backbone.history.getFragment()] );
Oder so von außerhalb Ihres Routers:
alert( myRouter.routes[Backbone.history.getFragment()] );
Backbone.history.getFragment()
, da Backbone.history.fragment
es sich um ein privates verstecktes Eigentum handelt.
Roberts Antwort ist interessant, aber leider funktioniert sie nur, wenn der Hash genau der Definition in der Route entspricht. Wenn Sie beispielsweise eine Route user(/:uid)
haben, wird diese nicht abgeglichen, wenn Backbone.history.fragment
entweder "user"
oder "user/1"
(beides sind die beiden offensichtlichsten Anwendungsfälle für eine solche Route). Mit anderen Worten, der passende Rückrufname wird nur gefunden, wenn der Hash genau ist "user(/:uid)"
(höchst unwahrscheinlich).
Da ich diese Funktionalität benötigte, erweiterte ich die um Backbone.Router
eine Funktion, die einen current
Teil des Codes wiederverwendet, den das Verlaufs- und Router-Objekt verwendet, um das aktuelle Fragment mit den definierten Routen abzugleichen, um den entsprechenden Rückruf auszulösen. Für meinen Anwendungsfall wird der optionale Parameter verwendet route
, der bei Einstellung auf "true" den entsprechenden für die Route definierten Funktionsnamen zurückgibt. Andernfalls wird das aktuelle Hash-Fragment von zurückgegeben Backbone.History.fragment
.
Sie können den Code zu Ihrem vorhandenen Extend hinzufügen, in dem Sie den Backbone-Router initialisieren und einrichten.
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'
Ich bin sicher, dass einige Verbesserungen vorgenommen werden könnten, aber dies ist ein guter Weg, um Ihnen den Einstieg zu erleichtern. Es ist auch einfach, diese Funktionalität zu erstellen, ohne das Route-Objekt zu erweitern. Ich habe dies getan, weil es der bequemste Weg für mein Setup war.
Ich habe dies noch nicht vollständig getestet. Bitte lassen Sie mich wissen, wenn etwas nach Süden geht.
Ich habe einige Änderungen an der Funktion vorgenommen. Anstatt entweder den Hash- oder den Routenrückrufnamen zurückzugeben, gebe ich ein Objekt mit Fragment, Parametern und Route zurück, damit Sie auf alle Daten der aktuellen Route zugreifen können, ähnlich wie Sie es von der Route tun würden. Veranstaltung.
Sie können die Änderungen unten sehen:
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
};
}
Weitere Kommentare und Erklärungen finden Sie im vorherigen Code. Sie sehen größtenteils gleich aus.
_.find
Funktion als festlegen this
, wodurch die Notwendigkeit für die Router
Variable entfällt (@DanAbramov hat dies bereits getan).
Marionette.AppRouter
, erweitern Sie Ihren Router mit der Funktion oben, aber Ersatz Router.appRoutes
für Router.routes
.
Um die aufrufende Route (oder URL) vom Handler für aufgerufene Routen abzurufen, können Sie sie durch Überprüfen abrufen
Backbone.history.location.href ... die vollständige URL Backbone.history.location.search ... Abfragezeichenfolge ab?
Ich bin auf der Suche nach dieser Antwort hierher gekommen, also sollte ich das, was ich gefunden habe, verlassen.
Wenn Sie die Root-Einstellung für den Router verwenden, können Sie sie auch einschließen, um das "echte" Fragment zu erhalten.
(Backbone.history.options.root || "") + "/" + Backbone.history.fragment
Hier ist ein bisschen ausführliche (oder, je nach Geschmack, besser lesbar) Version von Simon Antwort :
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
};
}
}
Wenn Sie sich die Quelle für das ansehen Router
, werden Sie feststellen, dass der Router, wenn er das Ereignis auslöst, dass sich etwas ändert, den Namen als "route: name" übergibt.
http://documentcloud.github.com/backbone/docs/backbone.html#section-84
Sie können das Ereignis "route" jederzeit in den Router einbinden und speichern, um die aktuelle Route abzurufen.
route
Ereignis, wenn dies trigger
nicht der Fall isttrue
(empfohlen und Standard).