0

Backbone コレクションに関連付けられているフラッシュ カードのコレクションがあります。コレクションを取得したら、プレーヤー モデルのインスタンスを作成します。

その後、ユーザーは「次へ」ボタンと「前へ」ボタンを使用して残りのフラッシュ カードをナビゲートできます。簡単だと思ったこれを行う最初の試みは、フラッシュカードをこのようなプレイヤーに渡すことでした。

残念ながら、この設計では、クリックされるたびに次と前のボタン イベントがバインドされます。そのため、たとえば次のボタンを初めてクリックした後、イベントが複数回発生し始めます。ゴースト ビューについてどこかで読んだことがありますが、以下のコードをチャンクに分割してゴースト ビューの問題を防ぐ方法が正確にわかりませんでした。

var flashCards = new Quiz.Collections.FlashCards({
        id: this.model.get('card_set_id')
});

Quiz.player = new Quiz.Models.FlashCardPlayer({
        collection: flashCards
})

Quiz.Models.FlashCardPlayer = Backbone.Model.extend({
defaults: {
    'currentCardIndex': 0
},

initialize: function(){
    this.collection = this.get('collection');
    this.showCard();

},

showCard: function(){
    var flashCard = this.collection.at(this.get('currentCardIndex'));
    var cardView = new Quiz.Views.FlashCardPlayer({
        model: flashCard
    });
},

currentFlashCard: function(){
    return this.get('currentCardIndex');
},

previousFlashCard: function(){
    var currentFlashCardIndex = parseInt(this.get('currentCardIndex'), 10);
    if(currentFlashCardIndex <= 0){
        console.log("no less");
    }
    this.set({
        'currentCardIndex': currentFlashCardIndex--
    });
    this.showCard();
},

nextFlashCard: function(){
    var currentFlashCardIndex = parseInt(this.get('currentCardIndex'), 10);
    if(currentFlashCardIndex >= this.collection.length){
        console.log("no more");
    }
    currentFlashCardIndex = currentFlashCardIndex + 1;
    this.set({
        'currentCardIndex': currentFlashCardIndex
    });
    console.log(this.get('currentCardIndex'));
    this.showCard();
 }
}); 


Quiz.Views.FlashCardPlayer = Backbone.View.extend({
   el: $('#cardSet'),
   tagName: 'div',
   _template: _.template($('#playerTemplate').html()),

initialize: function(){
    console.log("in view flashcardplayer", this);
    this.render();
},

events: {
    'click #previous': 'getPreviousCard',
    'click #next': 'getNextCard'
},

render: function(){
    $(this.el).html(this._template(this.model.toJSON()));
    return this;
},

getPreviousCard: function(){
    this.close();
    Quiz.player.previousFlashCard();
},

getNextCard: function(){
    this.close();
    Quiz.player.nextFlashCard();
}
});


script#playerTemplate(type="text/template")
<div id="state"></div>
<div id="previous">Previous</div>
<div id="card">
   <h2><%= question %></h2>
    <h3><%= answer %></h3> 
</div>
<div id="next">Next</div>
4

1 に答える 1

2

Quiz.Views.FlashCardPlayer新しいカードを表示するたびに新しいインスタンスを作成しています。これらのインスタンスはそれぞれ独自のイベント処理を行うため、各インスタンスは同じ#nextand#previous要素にバインドされます。

ここにはいくつかの概念的な問題があると思います。

  • FlashCardPlayer次/前の要素にイベントをバインドするビューが 1 つだけ必要です。おそらくFlashCard、1 枚のカードを表示する別のビューを用意する必要があります。プレーヤーは、次/前のボタンを押すと、それらのビューを入れ替えることができます。原則として、要素に が含まれている場合はid、単一のビュー インスタンスを使用して一度だけレンダリングしてバインドする必要があります。そうしないと、現在と同じ問題が発生します。

  • FlashCardPlayerモデルに詰め込みすぎています。原則として、モデルはデータのみを認識し、表示に使用されるビューについては認識しないようにする必要があります (1 つのモデルをさまざまなビューで表示する必要がある場合があるため)。コレクションに関するデータを格納する領域にあるため、モデルにnextFlashCard()andメソッドを使用してもかまいませんが、メソッドはプレゼンテーション ロジックを扱うため、実際にはビューの領域に真っ向から移行しています。ビューをモデルのイベントにバインドし、(または新しいメソッド) を使用して新しいカードの表示を処理することをお勧めします。previousFlashCard()showCard()change:currentCardIndexthis.model.get('currentCardIndex'))getCurrentCard()

于 2012-03-26T04:05:42.780 に答える