2011-10-19 10 views
11

私は、バックボーンルーターの適切な使い方の背後にあるアイディアを得られないと思います。ここに私が持っているものがあります:バックボーンルーター:最初にデータを取得するのを待つ

私は、ページが読み込まれたときに私がサーバから取り出したデータをいくつか持っており、それをモデルやコレクションにパックしています。これらのモデルとコレクションの数は不定です。私はルーターを使用して特定のコレクションのビューを最初から直接レンダリングできるようにしたいと考えています。

問題は次のとおりです。バックボーンルーターが早期に起動し、特定のビューにアクセスして、そのビューをまだ作成していないため、そのrenderアクションをトリガーすることはできません。つまり、実際にフェッチが完了した後でルートを起動させる必要があります。

これはそれを行うための適切な方法であれば、私は知らないが、私が思いついた唯一のアイデアはにある:別のトップレベルにルートの定義とBackbone.history.start();ビットをラップ

  1. -accesible関数(後で手動で呼び出す準備)
  2. 私のコレクションのfetch()
  3. のために、これらのコレクションの数が不明であるsuccessコールバックとして機能実行し、また、私はそれらのすべてがフェッチされた時を知る方法がない、と私は開始したくありませんルートを複数回だから私は_.defer()_.once()を使っている。

これは動作しますが、それは確かに非常に奇妙に見える:

ルータ:

window.startRoutes = _.once(function() { 

     var AccountPage = Backbone.Router.extend({ 

      routes: { 
      'set/:id': 'renderSet', 
      }, 

      renderSet: function(setId) { 

       /** … **/ 

       // Call the rendering method on the respective CardView 
       CardsViews[setId].render(); 

      } 

     }); 

     var AccountPageRouter = new AccountPage; 

     Backbone.history.start(); 

    }); 

はコレクション:だから私の質問は...私は右のそれを

window.CardsCollection = Backbone.Collection.extend({ 

    model: Card, 

    initialize: function(params) { 

     /** … **/ 

     // Get the initial data 
     this.fetch({success: function() { 
      _.defer(startRoutes); 
     }}); 

    }, 

}); 

をやっているのですか?それともこれを行う良い方法がありますか?

+0

なぜajaxコールをすぐに行うのですか?最初のデータのロードに必要なJSONをページにレンダリングし、データをバックボーンの開始点に渡すのはなぜですか? – redsquare

答えて

14

ルータを事前に定義することができます。 Backbone.History.start()を呼び出すまで何もしません。

あなたはこのように歴史を開始するには、あなたのコレクションで「リセット」イベントをバインドすることができます

my_collection.bind("reset", _.once(Backbone.History.start, Backbone.History)) 

は、ルータは、あなたのコレクションが完全にロードされたときのものをやって起動します。私はこれが正確にあなたが探しているものであるかどうかは分かりません。

私は、ルーティングを開始する前にどのコレクションをロードしたいのかを事前に知っていることを除いて、同様の状況があります。私はそうのように、私のルータにstartAfterメソッドを追加しました:

window.Workspace = new (Backbone.Router.extend({ 
    . . . 
    startAfter: function(collections) { 
     // Start history when required collections are loaded 
     var start = _.after(collections.length, _.once(function(){ 
     Backbone.history.start() 
     })) 
     _.each(collections, function(collection) { 
     collection.bind('reset', start, Backbone.history) 
     }); 
    } 
    })); 

、その後、私はセットアップ私のコレクションに

Workspace.startAfter([collection_a, collection_b, ...]) 

をした後、私はあなたと思うが、これは、あまりにもスタンドアローンモデルで動作するように適合させることができます'reset'イベント以外のものにバインドする必要があります。

私はあなたのサンプルコードを読んでうれしく思っています。_.onceと_.deferを使用すると正しい方向に私を指摘しました。

+0

これは 'my_collection.bind(" reset "、_.once(Backbone.history.start))'ではないのですか? – iblue

+2

'_.once()'に間違った引数を使用しました。私はこれを解決するためにあなたの答えを編集します。 kthxbye :) – iblue

+0

'_.once()'の例は私にとってはうまくいきませんでした。私は以下を使用しなければならなかった: 'app.users.on(" reset "、_.once(function){ Backbone.history.start(); }))' –

1

私は.render()メソッドをチェックするだけで、すべての必須フィールドが満たされてから使用しています。まだ塗りつぶされていない場合は、「Loading ... 'ウィジェットを表示しています。

私のすべてのビューはthis.model.bind('change', this.render, this);でモデル変更を購読しているので、モデルがロードされた直後にrender()が再度呼び出されます。

関連する問題