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


137

バックボーンを使用して、現在のルートの名前を取得することは可能ですか?ルート変更イベントにバインドする方法は知っていますが、変更間の別の時間に現在のルートを特定できるようにしたいと考えています。


「名前」とは、そのルートがバインドする関数を意味するのか、それとも現在のURLまたはURLのハッシュ部分が何であるのかを意味しますか?
ジョンマンシュ

1
ああ、はい、もっと具体的だったはずです。関数の名前を教えてください。(location.hashまたはBackbone.history.fragmentを実行して、URLのハッシュ部分を取得する方法を知っています。)
Drew Dara-Abrams '27

回答:


209

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

Backbone.history.getFragment();

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

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

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

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

または、ルーターの外からこのように:

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

ありがとうございます。ドキュメントでBackbone.history.fragmentについて言及したことは一度もないようです。これは新しい追加ですか、それとも文書化されていませんか?
Drew Dara-Abrams 2011

これは文書化されていないと思います。実際、私が初めてそれをどこで見たのか、ブログ、またはおそらくバックボーンのソースコードを覚えていません。
ロバート

25
参考までに、これは「foo /:id」や「bar * params」などのルートでは機能しません
wprl

2
は非表示のプライベートプロパティBackbone.history.getFragment()であるため、使用することBackbone.history.fragmentをお勧めします。
Vad

1
@Vadの提案に従って回答を修正しました。私はバックボーンをもう使っていませんが、彼のコメントは私には正しいように聞こえます。(以前の答えは、Backbone.history.getFragment()ではなくBackbone.history.fragmentでした)
Robert

57

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

この機能が必要だったので、HistoryオブジェクトとRouterオブジェクトが適切なコールバックをトリガーするために定義されたルートと現在のフラグメントを照合するために使用するコードの一部を再利用Backbone.Routerする- current関数でを拡張しました。私のユースケースでは、オプションのパラメーターを使用しますroute。これをtrueに設定すると、ルートに定義された対応する関数名が返されます。それ以外の場合は、現在のハッシュフラグメントをから返しますBackbone.History.fragment

バックボーンルーターを初期化およびセットアップする既存の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'

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

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


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

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


1
これを自分で書き込もうとしていたが、最初に解決策を探し出した。よかったです。あなたは私が欲しかったことを正確に行います、ありがとう!
Dan Abramov

これは、一見すると理解しやすいと思う、もう少し冗長なバージョンです。
Dan Abramov、2014年

4
わぁ、ありがとう!あなたは私たちのコードベースで承認を得ました。; Pマリオネット用に少し調整しました。ちなみに、ショートカット_.findとしてthis、関数の3番目のパラメーター(コンテキストを設定)をとして設定できるため、Router変数の必要性をなくすことができます(@DanAbramovがこれをすでに行いました)。
マーク

@マークこれらは朗報です。しかし、マリオネットでこの機能をどのように使用できますか?ドキュメントにはそれについて何もありません。
darksoulsong 14年

2
@darksoulsongを使用している場合はMarionette.AppRouter、上記の関数を使用してルーターを拡張しますが、の代わりに使用Router.appRoutesRouter.routesます。
マーク

11

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

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

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


6

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

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

6

これは、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
    };
  }
}

4

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

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

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


OK、これは「自分で構築する」ようなものだと思います。
Drew Dara-Abrams、

そうですが、そうでないroute場合trigger イベントを取得できませんtrue(推奨&デフォルト)。
Dan Abramov、2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.