webentwicklung-frage-antwort-db.com.de

Backbone.js: Aktuelle Route abrufen

Kann ich mit Backbone den Namen der aktuellen Route abrufen? Ich weiß, wie man sich an Routenänderungsereignisse bindet, aber ich möchte in der Lage sein, die aktuelle Route zwischen den Änderungen zu anderen Zeiten zu bestimmen.

134

Wenn Sie in Ihrer Anwendung einen Router instanziiert haben, gibt die folgende Zeile das aktuelle Fragment zurück:

Backbone.history.getFragment();

Aus der Backbone.js-Dokumentation :

"[...] Der Verlauf dient als globaler Router (pro Frame), um Hash-Änderungsereignisse oder Push-Status zu verarbeiten, die entsprechende Route abzugleichen und Rückrufe auszulösen. Sie sollten niemals selbst einen dieser Router erstellen müssen - Sie sollten den Verweis auf Backbone.history verwenden, der 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 Bereich Ihres Routers Folgendes vornehmen:

alert( this.routes[Backbone.history.getFragment()] );

Oder wie folgt von außerhalb Ihres Routers:

alert( myRouter.routes[Backbone.history.getFragment()] );
208
Robert

Roberts Antwort ist interessant, aber leider funktioniert es nur, wenn der Hash genau wie in der Route definiert ist. Wenn Sie zum Beispiel eine Route für user(/:uid) haben, wird diese nicht gefunden, wenn Backbone.history.fragment Entweder "user" Oder "user/1" Ist (beides sind die beiden) offensichtlichsten Anwendungsfälle für eine solche Route). Mit anderen Worten, es wird nur der entsprechende Rückrufname gefunden, wenn der Hash genau "user(/:uid)" ist (höchst unwahrscheinlich).

Da ich diese Funktionalität benötigte, erweiterte ich die Backbone.Router - Funktion um eine current- Funktion, die einen Teil des Codes, den das History- und Router-Objekt verwendet, wiederverwendet, um das aktuelle Fragment mit den definierten Routen abzugleichen, um den entsprechenden Rückruf auszulösen . Für meinen Anwendungsfall wird der optionale Parameter route verwendet, der, wenn er auf etwas Wahres gesetzt ist, den entsprechenden Funktionsnamen zurückgibt, der für die Route definiert wurde. Andernfalls wird das aktuelle Hash-Fragment von Backbone.History.fragment Zurückgegeben.

Sie können den Code zu Ihrem vorhandenen Extend hinzufügen, um den Backbone-Router zu initialisieren und einzurichten.

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 das gemacht, weil es die bequemste Art für mein Setup war.

Ich habe das noch nicht vollständig getestet, also lass es mich wissen, wenn etwas nach Süden geht.


UPDATE 25.04.2013

Ich habe einige Änderungen an der Funktion vorgenommen. Anstatt entweder den Hash- oder den Route-Callback-Namen zurückzugeben, gebe ich ein Objekt mit Fragment, Parametern und Route zurück, sodass Sie auf alle Daten der aktuellen Route zugreifen können, so wie Sie es von der Route aus 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.

56
Simon Kjellberg

Um die aufrufende Route (oder URL) vom aufgerufenen Routen-Handler 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 denke ich, ich sollte das, was ich gefunden habe, verlassen.

9
yoshi

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
6
user1310662

Hier ist eine kleine ausführlichere (oder je nach Geschmack besser lesbare) Version von Simons 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
    };
  }
}
5
Dan Abramov

Wenn Sie sich die Quelle für Router ansehen, werden Sie feststellen, dass der Router, wenn er das Ereignis auslöst, das besagt, 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 am Router einbinden und speichern, um die aktuelle Route abzurufen.

4
Brian Genisio