web-dev-qa-db-ja.com

backbone.jsのナビゲート関数でトリガーをtrueと呼ぶのは悪い習慣と考えられているのはなぜですか?

Backbone.history.navigate関数の呼び出しは悪い習慣と見なされていることをいくつかの場所で読んだことがあります。

たとえば、Addy Osmaniは著書「Developing Backbone.js Applications」でこれを使用しています。

また、Router.navigate()は、trigger:trueオプションを渡すことで、URLフラグメントの更新とともにルートをトリガーすることもできます。注:この使用はお勧めできません...

http://addyosmani.github.io/backbone-fundamentals/#backbone.history

または、Derick Baileyの彼の blog post sais:

ほとんどの場合、アプリケーション内からルートのハンドラを実行するべきではありません。

しかし、私はその背後にある理由と、より良い解決策が何であるかを本当に理解していません。

私の意見では、trigger:trueオプションを指定してナビゲート関数を呼び出すことはそれほど悪くありません。 route関数は、呼び出し時に、考慮されたデータが既に読み込まれているかどうかを常にチェックし、すべての作業を最初からやり直す代わりに、この読み込まれたデータを表示します...

32
DanEEStar

_Router#navigate_が正確に何をするのかについて、いくつかの混乱があるように思います。

オプションを設定しないと、指定されたフラグメントにURLが更新されます。例えば。 router.navigate('todo/4/edit')RLを更新から_#todo/4_に、さらにそのURLに対してブラウザの履歴エントリを作成します。 ルートハンドラーは実行されません

ただし、_trigger:true_を設定するとURLは更新されますが、ハンドラも実行されますそのルートに指定されたものです(Addyの例では、ルーターeditTodo関数を呼び出します)ブラウザの履歴エントリを作成します。

_replace:true_を渡すと、URLが更新され、ハンドラーは呼び出されませんが、ブラウザーの履歴エントリは作成されません

次に、答えは次のとおりです。

_trigger:true_の使用が推奨されない理由は単純です。アプリケーションの状態からアプリケーションの状態にナビゲートするには、ほとんどの場合、特定のアプリケーションの状態に直接ナビゲートする場合とは異なるコードを実行する必要があります。

アプリケーションに状態A、B、Cがあるとします。ただし、状態Bは状態Aに基づいて構築され、状態CはBに基づいて構築されます。その場合、BからCに移動するときにコードの特定の部分のみを実行する必要がありますが、状態Cに直接アクセスすると、おそらくいくつかの状態チェックと準備が実行されます。 :

  • thatデータが読み込まれましたか?そうでない場合は、ロードしてください。
  • ユーザーはログインしていますか?リダイレクトしない場合。

等.

例を見てみましょう:状態A(_#list_)は曲のリストを表示します。状態B(_#login_)はユーザー認証に関するものであり、状態C(_#list/edit_)では曲のリストを編集できます。

したがって、ユーザーが状態Aに到達すると、曲のリストがロードされ、コレクションに格納されます。ログインボタンをクリックすると、ログインフォームにリダイレクトされます。彼は認証に成功し、曲リストにリダイレクトされますが、今回は曲の横にある削除ボタンを使用します。

彼は最後の状態(_#list/edit_)をブックマークします。

さて、数日後、ユーザーがブックマークをクリックするとどうなるでしょうか。アプリケーションは曲をロードする必要があり、ユーザーが(まだ)ログインしていることを確認し、それに応じて反応する必要があります。状態遷移フローでは、他の状態で既に行われているものです。

今私自身のメモのために:

例のように、実際のアプリケーションで上記のアプローチを推奨することは決してありません。あなたはすべきですBからCに移動するときにコレクションがロードされているかどうかを確認します。同様に、ユーザーが実際にログインしているかどうかを確認する必要があります。これは単なる例です。

IMOルーターは実際には特別な種類のビュー(考えてみてください。アプリケーションの状態を表示し、ユーザー入力をアプリケーションの状態/イベントに変換します)であり、常にそのように扱われる必要があります。決してrelyルーター間で状態を遷移させるが、ルーターに状態遷移を反映させる。

25
Creynders

ここでの@Stephenの答えに同意する必要があります。そして、その主な理由は、router.navigate({trigger : true})の使用がアプリケーションの状態を処理する役割をルーターに与えるためです。 reflectアプリケーションの状態のみを制御し、制御するべきではありません。

また、ウィンドウのハッシュを変更するのはViewの責任ではありません。これはルーターのonlyジョブです!それを奪わないでください!優れたモジュール性と懸念事項の分離により、スケーラブルでメンテナンス可能なアプリケーションが実現します。

アプリケーション内の新しいセクションに人を転送する

バックボーンはイベント駆動型フレームワークであり、イベントを使用して通信します。機能はルーターにあるべきではないので、router.navigate({ trigger : true })を呼び出す必要はまったくありません。これは私がルーターをどのように使用するかの例であり、優れたモジュール性と懸念の分離を促進すると思います。

var Router = Backbone.Router.extend({
  initialize: function(app) {
    this.app = app;
  },
  routes: {
    'videoLibrary' : function() { this.app.videoLibrary(); }
  }
});

var Application = _.extend({}, Backbone.Events, {
  initialize: function() {
    this.router = new Router( this );
    this.listenTo( Backbone, 'video:uploaded', function() { 
      this.router.navigate('/videoLibrary');
      this.videoLibrary();
    });
  },
  videoLibrary: function() {
    //do useful stuff
  }
});

var uploadView = Backbone.View.extend({
  //...
  uploadVideo: function() {
    $.ajax({
      //...
      success: function() { Backbone.trigger('video:uploaded'); }
    });
  }
});

あなたのビューしないユーザーがアップロードを完了したときに何をすべきかを知りたい、または知りたい、これは他の誰かの責任です。この例では、ルーターはアプリケーションの機能の単なるエントリポイントであり、uploadViewによって生成されるイベントは別のものです。ルータは常にハッシュの変更と履歴を通じてアプリケーションの状態を反映しますが、機能は実装していません。

テスト容易性

懸念事項を分離することで、アプリケーションのテスト容易性を高めます。スパイをするのは簡単ですBackbone.triggerとビューが正しく機能していることを確認します。ルーターをモックするのは簡単ではありません。

モジュール管理

また、AMDやCommonJSなどのモジュール管理を使用している場合、それを呼び出すには、アプリケーション内のあらゆる場所でルーターのインスタンスを渡す必要があります。したがって、アプリケーションに密接な結合があると、これは望ましくありません。

11
mor

私の意見では、Ruby on Railsアプリケーションではなく、デスクトップアプリケーションのようなものです。

RoRとは、ルーティングがコントローラーへの特定の呼び出しに移動して特定のアクションを実行するという意味でルーティングをサポートするフレームワークを指しているだけです(CRUD操作を想像してください)。

Backbone.historyは、ユーザーが特定のURLを保存して後でもう一度実行できるようにするためのブックマークとして意図されています。この場合、彼は以前に残したのと同じ状況を見つけるでしょう。

あなたが言う時:

私の意見では、trigger:trueオプションを指定してナビゲート関数を呼び出すことはそれほど悪くありません。ルート関数は、呼び出し時に常に、検討されたデータが既にロードされているかどうかを常にチェックし、すべての作業を最初からやり直す代わりに、このロードされたデータを表示します...

それは私にはにおいがします。ルートをトリガーしていて、データがあるかどうかを確認するためにルートをトリガーしている場合は、実際にルートが既にあるため、同じデータでDOM全体を再度ロードせずに、それに応じてビューを変更する必要があります。

とは言ってもtrigger:trueはあるので、それを使用する理由はありますか?私の意見では、ビューを完全に交換している場合は、それを使用することが可能です。

2つのタブを持つアプリケーションがあるとします。1つは単一のリソースを作成でき、もう1つは作成されたリソースのリストを表示できます。 2番目のタブでは実際にコレクションを読み込んでいるため、2つのタブでデータが異なります。この場合、trigger:trueを使用します。

とは言っても、私は2週間バックボーンを使用しているので、この世界にはかなり慣れていませんが、このオプションの使用をやめるのは理にかなっているように思えます。

3
dierre

状況によって異なります。

移動しようとしているビューに影響を与える可能性がある現在のビューで何かを行った場合(たとえば、顧客レコードを削除するための作成)、triggerをtrueに設定することは正しいことです。

それについて考えてください。顧客レコードを削除した場合、顧客のリストを更新してその削除を反映したくないですか?

1
l3x