2

Backbone で ToDo リストのサンプル プロジェクトに取り組んでいます。入れ子になったリストのシナリオで、フレームワークがビューとモデルをどのように編成することを好むかを理解したいと思います。

これが何を意味するのかを明確にするために、単一ページの Backbone アプリは ToDo リストのリストを表示する必要があります。バックエンドの観点から見ると、List リソースと Item (todo リスト内の 1 つのエントリ) リソースがあります。次のようなもの:

  • 月曜日の家事
    • メールを受け取る
    • 洗濯する
    • ドライクリーニングを受け取る
  • 食料品リスト
    • セロリ
    • 牛肉
    • あなたはアイデアを得る...

私は Rails 3.2 アプリなので、漠然と Railscasts Backbone.js チュートリアルに従っています。現在のデザインはそこから取得しています。バックボーンで規定されたパターンから大きく外れているのか、それとも正しい軌道に乗っているのか知りたいです!

私はこれまでに持っています:

ListsIndex View                         //index of all lists
\-- ListsCollection
     \-- ListView / Model               //individual list
          \-- ItemsIndex View           //index of items in one list
              \-- ItemsCollection
                  \-- Item View / Model //individual todo item

フローは次のようになります。

  1. ルーターの初期化時に、/lists バックエンド ルートでのリストの fetch() コレクション。ListsIndex のコレクション部分の「リセット」イベントで、コレクション内の各項目に対して render() を実行し、リスト インデックス ビュー テンプレートに追加します。
  2. 各アイテム ビューの初期化メソッドで (これは、第 2 レベルのフェッチを接続する場所ですか? ) fetch() は、/lists/:id/items バックエンド ルートからそのビューに固有の ItemsCollection にアイテムをルーティングします。
  3. 同じメソッドで、ItemsIndex オブジェクトをインスタンス化し、コレクションをそれに渡します。繰り返しますが、ItemsIndex には、コレクションが作成されたときの「リセット」イベント ハンドラーがあり、その時点で、アイテム コレクションからフェッチされた各モデルをレンダリングし、独自のビューに追加する必要があります。

私は基本的にリストのデザインを採用し、それを 1 レベル下の項目にミラーリングしています。違いは、頼りになるルーターがなくなったことです。したがって、ListView の initialize メソッドを使用して、同様の効果を得ています。

ええ/いいえ?超間違い?ありがとう!

4

1 に答える 1

3

TL:DR; 1) fetch() reset() の代わりに初期データをブートストラップします。2)必要に応じて、ビューの初期化でフェッチを実行できます。または、最初にデータをロードすることもできます。init でフェッチすると、非同期の性質により、レンダリング時にデータの準備ができていないことに注意してください。その同期/追加/などを待っているリスナーがいる場合は問題ありません。3) itemIndex オブジェクトの意味がわかりませんが、必要に応じてオブジェクトを作成し、それらにコレクションを追加できます。または、すべてのリストが最終的にコレクションを持つことがわかっている場合は、最初に焼き込むことができます。必要に応じてリセットできます (オプション {add:true} を指定しない限り、fetch は自動的にこれを行います)。人々が完全な fetch() で物事を行う一般的な方法。

見た目はかなりいいと思います。Backbone の良いところは、さまざまな方法で実行できることです。たとえば、番号 2 は、ビューから 2 番目の fetch() を接続することを示しています。遅延ロードが必要な場合は、それを行うことができます。または、何かが完了する前に、アプリの開始時にすべてのデータを取得することもできます。それは本当にあなた次第です。これは私がそれを行うかもしれない方法です。

これは、このようなアプリを作成する方法です(私の好みです。それがより良いか悪いか、またはあなたが説明したものと同じかどうかはわかりません。)

まず、ListModel というモデルを作成します。ID と名前の属性があります。このようにして、個別に取得できる独自の ID を持つ多数の個別のリストを作成できます。

各 ListModel には、その中に ItemsCollection があります。このコレクションには、その一部である ListModel に基づく URL があります。したがって、ListModel-1 のコレクション URL は /list/1 のようになります。

最後に、リソース ID とテキストである ItemModel があります。

ListCollection
    ListModel  // Monday Chores
        ItemCollection
            ItemModel  // Mail
            ItemModel  // Laundry
            ItemModel  // Drycleaning
    ListModel  // Grocery
        ItemCollection
            ItemModel  // Celery
            ItemModel  // Beef

したがって、この小さな表示では、まだビューに関係するものを何も入れていないことに気付くでしょう。それがより概念的なものかどうかはわかりませんが、これはデータ階層がどのように見えるかであり、ビューはそれから完全に独立している必要があります。上記のビューをどのように含めているのか正確にはわかりませんでしたが、これでより明確になると思いました。

これらの構造の定義に関して、私は 2 つのことを考えています。

まず、ListModel がコレクションで定義されていることを確認します。そうすれば、コレクション add(hash) を使用して、新しいモデルを作成/追加するときにインスタンス化できます。

次に、ListModel が作成されると、ItemCollection がその ListModel オブジェクトのプロパティとして (属性としてではなく) 自動的に作成されるように、ListModel を定義します。

理想的には、ListModels は次のようになります。

ListModel.ItemCollection

アプリが初期化される前に、fetch() ではなくデータをブートストラップします。(この種の対処ポイント 1) 理想的には、バックボーン アプリケーションの開始時に、最初から必要なすべてのデータが含まれている必要があります。次のようなデータを head に渡します。

 var lists = [listModel-1-hash, listModel-2-hash];

アプリが起動すると、すぐにこれら 2 つのリストを作成できます。

var myLists = new ListCollection();

_.each(lists, function(hash) {
    myLists.add(hash);  // Assumes you have defined your model in the ListCollection
}

これで、リスト コレクションに必要なすべてのリスト モデルが含まれました。

ここでビューの出番です。どのビューにも何でも渡すことができます。しかし、ビューを 3 つに分類することができます。

AppView、ListModelView、ItemModelView、それだけです。

次のような構造を想像してください。

<body> // AppView
    <ul class="List"> // ListModelView
        <li class="Item"></li>     // ItemModelView
    </ul>
    <ul class="List"> // ListModelView
    </ul>
</body>

アプリを起動して AppView を作成すると、AppView 内で各 ListModelView が生成され、本体に追加されます。私たちのリストは空です。おそらく、クリックするとアイテムが遅延ロードされます。これがあなたがそれを接続する方法です。

// In ListModelView
events: {'click':'fetchItems'}

fetchItems: function() {
    this.model.itemCollection.fetch();  // Assumes you passed in the ListModel into view
}

最初にデータをブートストラップしたので、この fetch() 呼び出しが「2 回目の」フェッチになります。(私はあなたが作ったポイント2に取り組んでいます。)初期化でそれを取得できます。これは非同期関数であるため、レンダリング時に必要な場合は機能しないことに注意してください。しかし、できることは、itemCollections への追加イベントをリッスンしているこのビューにイベント リスナーを追加することです。

this.model.itemCollection.on('add', this.addItemView, this);

addItemView()itemViews の新しいインスタンスを生成し、それらを追加します。

ポイント 3 については、必要な時点でコレクションをインスタンス化し、それを ListModel にスローできます。または、私が行ったことを実行して、すべてのモデルに常に ItemCollection があることを確認することもできます。これは、好みや目標によって異なります。あなたはおそらくこれすべてを必要としませんでしたが、何らかの理由でそれを説明したいと思いました. わからない、多分それは役立つ。

于 2012-08-22T11:01:42.967 に答える