Магистраль - как реорганизовать этот код, чтобы предотвратить призрачные представления - PullRequest
0 голосов
/ 26 марта 2012

У меня есть коллекция флэш-карт, которые привязаны к коллекции 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();
}

}); * +1011 *

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>

1 Ответ

2 голосов
/ 26 марта 2012

Вы создаете новый экземпляр Quiz.Views.FlashCardPlayer каждый раз, когда показываете новую карту.Каждый из этих экземпляров выполняет свою собственную обработку событий, поэтому каждый экземпляр привязывается к одним и тем же #next и #previous элементам.

Я думаю, что здесь есть несколько концептуальных проблем:

  • Вам нужен только один FlashCardPlayer просмотр, который должен связывать события на следующих / предыдущих элементах.Вероятно, у вас должен быть отдельный вид FlashCard, который отображает одну карту, и игрок может менять местами эти виды при нажатии следующих / предыдущих кнопок.Как правило, если у вас есть элемент с id, вы должны выполнять рендеринг и привязку к нему только один раз, с одним экземпляром представления, в противном случае вы столкнетесь с той же проблемой, что и сейчас.

  • Вы пытаетесь вложить слишком много в модель FlashCardPlayer.Как правило, модели должны знать только о своих данных, а не о представлениях, используемых для их отображения (отчасти потому, что одна модель может потребоваться отображать в различных видах).Я не возражаю против использования в модели методов nextFlashCard() и previousFlashCard(), поскольку это все еще относится к области хранения данных о сборе, но метод showCard() действительно перемещается прямо на территорию просмотра, посколькус логикой представления.Гораздо лучшая идея - привязать view к событию change:currentCardIndex на модели и обработать отображение новой карты, используя this.model.get('currentCardIndex')) (или новый метод getCurrentCard()), чтобы получитьит.

...