Backbone: router.navigateは、ハッシュが変更されない限りルーターを呼び出しません

作成日 2011年10月02日  ·  22コメント  ·  ソース: jashkenas/backbone

シバンのないURLを使おうとしていますが、これはいくつかの悲しみを引き起こしています。

私がテストするとき、私はこれをしました。

<a href="#" onclick="router.navigate('/albums/<%= album.id %>', true); return false;">Show</a>

URLが更新されましたが、ルーターが呼び出されません。 最初はルートが一致していないと思いましたが、ページを更新するとルートは正常に一致しています。

それから私はこれを試しました:

<a href="#" onclick="router.navigate('/albums/<%= album.id %>', true);">Show</a>

そして、すべてが正常に機能します。ルーターは、ハッシュ変更がトリガーされた場合にのみ呼び出されるようです。

最も参考になるコメント

これは確かに、ルートを強制的にリロードしようとしたときに遭遇したrouter.navigate()興味深い動作です。 これが私がやったことです:

Backbone.history.loadUrl( Backbone.history.fragment )

これはAPIの一部として_明示的に_文書化されていませんが、確かに仕事を成し遂げます。 router.navigate( 'current/path', true )がルートハンドラーを再度呼び出すようにトリガーする必要があることは、私には合理的なようです。

他の誰かがこれにチャイムを入れたいですか?

全てのコメント22件

イニシャルを削除すると動作します/
それはあなたのルートと完全に一致する必要があると思います

これは確かに、ルートを強制的にリロードしようとしたときに遭遇したrouter.navigate()興味深い動作です。 これが私がやったことです:

Backbone.history.loadUrl( Backbone.history.fragment )

これはAPIの一部として_明示的に_文書化されていませんが、確かに仕事を成し遂げます。 router.navigate( 'current/path', true )がルートハンドラーを再度呼び出すようにトリガーする必要があることは、私には合理的なようです。

他の誰かがこれにチャイムを入れたいですか?

私もこの問題に遭遇しました。 これが私の特定のユースケースです:

私はメディアクエリを使用して、すべての画面サイズに対応するインターフェイスを提供しています。 私のビューには、メディアクエリに応答しない要素がいくつか含まれているため、サイズ変更イベントをリッスンし、必要に応じてページを再レンダリングする関数を作成しました。 個々のビューを参照してレンダリングするのではなく、

router.navigate(Backbone.history.fragment, true)

Backbone.historyをまったく参照する必要はありません。 ルータにrefreshまたはreloadメソッドがあると最適です。

router.refresh(true);

私も同じ問題を抱えていました。 @Ansmanあなたはあなたのルートが何であるかを示すことができますか? 私の問題は、先頭のスラッシュがデフォルトのルートであるため、ハッシュを取得するときに履歴によって自動的に削除されることでした。

はい-ルートまたはnavigate()呼び出しのいずれにも、先頭にスラッシュを付けないでください。 とは言うものの、マスターにはすべての先頭のスラッシュを強制的に削除するコミットがあるため、これによってバグのある動作が発生することはなくなります。

最後に、はい、ルーターはルートが実際に変更された場合にのみ起動する必要があります。

router.navigate( "route"、true)への明示的な呼び出しは、ハッシュでルートが変更されていない場合でもルートをトリガーする必要があることをチャイムしたいと思います。

@danrobertsハッシュが変更されていない場合、現時点ではルートを強制的にトリガーすることはできないようです。 router.navigate( "route /"、{trigger:true});を試しました。 そしてそれは機能しません。 簡単なハックは、単にrouter.route_name()呼び出すことです。

@olalonde上記の@wookiehangoverの方法を使用して、良い結果が得られました。 移動しようとしているルートが現在のハッシュと同じであるかどうかを確認し、router.navigateまたはhistory.loadURLのいずれかを呼び出すカスタム関数を作成しました。

これがoptions配列の一部である可能性があることは合理的であるように思われます。これは、ルートに関係なくトリガーする場合は、 refresh:trueのようなものです。 また、{trigger:true}が論理的にルートをトリガーするため、ドキュメントの更新が適切であるように思われるかもしれません...

このバグを閉じることで私が抱えている問題は次のとおりです。

バックボーンを使用する際の重要なポイントは、ルートの解析を処理してから、ルートに基づいて関数を呼び出すことです。 「リロード」がバックボーンを介して直接問題ないかどうかを判断する機能がないため、この効果を実現するために何かを行う必要があります。

        if (url == window.location.pathname + window.location.search) {
            Backbone.history.loadUrl(url);
            return false;
        }
        else if (app.router.isHandled(url)) {
            Backbone.history.navigate(url, {
                trigger: true
            });
            return false;
        }

これは機能しますか? ええ、でもこれは完全に有効なユースケースであり、プラットフォームに含めるとよいと思います。

参考までに、このスレッドの前に#1214を見て、同じコメントを投稿しました。

バックボーンルーターは、URL変更イベントをリッスンしてルーティングされたアクションをトリガーするため、このタイプのアクションを許可しません。

アクションをトリガーするコントロールをインターセプトし、ルーターのアクションをリセットする必要があります。

ここでjsFiddleの例を作成しました:
http://goo.gl/wPulo

とここにブログ投稿:
http://goo.gl/mJM2i

今日この問題に遭遇し、私の2セントを追加したいと思います。

trigger: true明示的に設定すると、ハッシュが変更されない限りイベントがトリガーされないという直感的でない動作のようです。

私の投票は、条件に関係なくルートをトリガーするtrigger: trueに賛成です。

実際の例の1つは、現在のページを更新する場合です。これは、現在のtrigger: true動作では不可能です。

KenPerkinsメソッドまたはBBルーターに統合される類似のものの場合は+1。

{trigger:true}が渡された場合、プロセスが同じページをナビゲートするための+1

roter.navigate()メソッドがアプリケーションで機能しない理由を見つけるために3時間を費やしました。 BBのドキュメントには、この問題に関する通知を含める必要があると思います。

私の醜いが迅速な解決策は、実際のメソッドの前にrouter.navigate()メソッドを呼び出すこと

router.navigate();
router.navigate("app", true);

今のところ、それは機能しました。 しかし、 refresh:trueオプションがあれば、私は間違いなくそれを使用します...

これは私が今日遭遇した問題なので、これについての私の考えを残してください。 {trigger: true}オプションハッシュをrouter.navigateに明示的に渡したときに、ルートが呼び出されないことは非常に直感的ではないようです。 @onuradsayのようなrefresh:trueオプションの追加が提案されているのを見て

@patrickod@onuradsayのアイデアの実用性のための+1

+1。 それでもイベントを受信して​​、アプリで更新が必要かどうかを判断できるはずです。 上記のハックの多くでこれを理解できますが、あまりきれいではありません。 この動作は、ルーターに配置するのに十分なほど一般的だと思います。

私はそれが起こらないのではないかと心配しています。 人々がそれを求めているという事実は、実際には、イベントを無条件に発生させることよりも、 trigger:trueを_削除_することへの推進力です。 説明させてください:

バックボーンのイベントはすべて、状態が変更されたときに通知されることに関するものです。 モデルの場合と同じように、次のことを行います。

model.set({title: "Boom"})
model.set({title: "Boom"})

...状態が変更されていないため、2回目にイベントがトリガーされることはありません...すでにいる場所に移動しようとしても、状態が変化することはなく、イベントがトリガーされません。

ボタンがクリックされるたびにコールバックを起動させたい場合は、コールバックを追加するだけです。 または、Backboneのイベントを使用してそれを実行する場合は、object.trigger( "myEvent")を呼び出すだけです。

trigger:true代わりに、trueと見なされ、 silent:falseオプションがあるようです。

ただし、この機能を追加しない場合は、ボタンハンドラーで常にこのようなことを行う必要があります-

if (Backbone.history.fragment === 'foo') {
    Backbone.history.loadUrl(Backbone.history.fragment);
 } else {
     router.navigate('foo', {'trigger': true});
}

素晴らしいトリックをありがとう@dankantor

(同じページ/ハッシュのリロードを強制するために)このユースケースを実行する必要がある場合は、history.fragmentの代わりにBackbone.history.getFragment()を実行して、履歴のプロパティにアクセスしないようにしませんか? きれいなようです。

リロードを強制するBackbone.history.refreshメソッドを作成しました。 次に、一部のプロジェクトでは、ハッシュが変更されたかどうかに関係なく、デフォルトのナビゲート動作をオーバーライドしてリロードします。

      _.extend(Backbone.History.prototype, {
            refresh: function() {
                this.loadUrl(this.fragment);
            }
        });

        var routeStripper = /^[#\/]/;
        var origNavigate = Backbone.History.prototype.navigate;
        Backbone.History.prototype.navigate = function (fragment, options) {
            var frag = (fragment || '').replace(routeStripper, '');
            if (this.fragment == frag)
                this.refresh();
            else
                origNavigate.call(this, fragment, options);
        };
このページは役に立ちましたか?
0 / 5 - 0 評価