我有一些与骨干网相关的闪存卡。获取收藏集后,我将创建一个播放器模型的实例。

然后,用户可以使用“下一个”和“上一个”按钮浏览其余的闪存卡。我认为这很简单,这是我第一次刺入,将闪卡传递给这样的玩家。

不幸的是,这种设计导致每次单击时都绑定下一个和上一个按钮事件。因此,例如在第一次单击下一个按钮之后,该事件开始触发多次。我在某处读到了有关鬼视图的信息,但无法完全弄清楚如何将下面的代码分解成一个大块,这将有助于防止鬼视图问题。

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>

最佳答案

每次显示新卡时,您都在创建Quiz.Views.FlashCardPlayer的新实例。这些实例中的每一个都执行自己的事件处理,因此,每个实例都绑定到相同的#next#previous元素。

我认为这里有两个概念性问题:


您只需要一个FlashCardPlayer视图,该视图应将事件绑定到下一个/上一个元素。您可能应该有一个单独的FlashCard视图,该视图显示一张卡,并且在按下下一个/上一个按钮时,播放器可以将这些视图内外交换。通常,如果您的元素带有id,则只能使用单个视图实例对它进行渲染和绑定一次,否则最终会遇到与现在相同的问题。
您试图将太多内容塞入FlashCardPlayer模型。通常,模型应该只知道其数据,而不是用于显示数据的视图(部分原因是一个模型可能需要在各种视图中显示)。我不介意在模型上使用nextFlashCard()previousFlashCard()方法,因为这仍然是存储有关集合的数据的领域,但是showCard()方法实际上可以直接进入视图区域,因为它处理具有演示逻辑。更好的主意是使用change:currentCardIndex(或新的this.model.get('currentCardIndex'))方法)将视图绑定到模型上的getCurrentCard()事件并处理新卡的显示。

09-25 22:25