web-dev-qa-db-ja.com

Backbone.js:現在のルートを取得

Backboneを使用すると、現在のルートの名前を取得できますか?ルート変更イベントにバインドする方法は知っていますが、変更の合間に他の時間に現在のルートを決定できるようにしたいと思います。

134

アプリケーションでルーターをインスタンス化した場合、次の行は現在のフラグメントを返します。

Backbone.history.getFragment();

Backbone.jsドキュメント から:

"[...]履歴はグローバルルーターとして機能し(フレームごと)、hashchangeイベントまたはpushStateを処理し、適切なルートに一致し、コールバックをトリガーします。これらのいずれかを自分で作成する必要はありません—ルート付きのルーターを使用する場合、自動的に作成されるBackbone.historyへの参照を使用する必要があります。 [...] "

そのフラグメントにバインドされた関数の名前が必要な場合は、ルーターのスコープ内で次のようなものを作成できます。

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

または、ルーターの外部から次のようにします。

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

ロバートの答え は興味深いですが、悲しいことに、ハッシュがルートで正確に定義されている場合にのみ機能します。たとえば、user(/:uid)のルートがある場合、Backbone.history.fragment"user"または"user/1"の場合は一致しません(どちらも最も明白な2つのユースケースです)そのようなルート)。言い換えると、ハッシュが正確に"user(/:uid)"である場合のみ(適切ではない)、適切なコールバック名を見つけます。

この機能が必要だったため、Backbone.Routercurrent関数で拡張しました。この関数は、適切なコールバックをトリガーする定義済みのルートに対して現在のフラグメントを一致させるために使用するコードの一部を再利用します。私の使用例では、オプションのパラメーターrouteを取ります。このパラメーターは、真に設定すると、ルートに定義された対応する関数名を返します。それ以外の場合は、Backbone.History.fragmentから現在のハッシュフラグメントを返します。

Backboneルーターを初期化およびセットアップする既存のExtendにコードを追加できます。

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'

いくつかの改善ができると確信していますが、これはあなたが始めるための良い方法です。また、ルートオブジェクトを拡張せずにこの機能を簡単に作成できます。私のセットアップにとって最も便利な方法だったので、これをしました。

私はまだこれを完全にテストしていないので、何かが南に行くかどうか教えてください。


2013年4月25日更新

私は関数にいくつかの変更を加えたので、ハッシュまたはルートのコールバック名を返す代わりに、フラグメント、パラメータ、およびルートを持つオブジェクトを返すので、ルートからのように現在のルートからすべてのデータにアクセスできますイベント。

以下の変更を確認できます。

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
    };
}

さらなるコメントと説明については、前のコードを参照してください。ほとんど同じように見えます。

56
Simon Kjellberg

呼び出されたルートハンドラーから呼び出し元のルート(またはURL)を取得するには、チェックすることで取得できます。

 Backbone.history.location.href ...完全なURL 
 Backbone.history.location.search ...?
で始まるクエリ文字列

私はこの答えを探してここに来たので、見つけたものを残すべきだと思います。

9
yoshi

ルーターのルート設定を使用する場合は、それを含めて「実際の」フラグメントを取得することもできます。

(Backbone.history.options.root || "") + "/" + Backbone.history.fragment
6
user1310662

サイモンの答えtadより冗長な(または、好みに応じて、より読みやすい)バージョンがあります:

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

Routerのソースを見ると、ルーターが何かを変更するイベントをトリガーすると、名前が「route:name」として渡されることがわかります。

http://documentcloud.github.com/backbone/docs/backbone.html#section-84

いつでもルーターの「ルート」イベントをフックして保存し、現在のルートを取得できます。

4
Brian Genisio