簡體   English   中英

Backbone - 如何重構此代碼以防止出現鬼視圖?

[英]Backbone - how to refactor this code to prevent ghost views?

我有一系列與 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>

每次顯示新卡片時,您都在創建Quiz.Views.FlashCardPlayer的新實例。 這些實例中的每一個都執行自己的事件處理,因此每個實例都綁定到相同的#next#previous元素。

我認為這里有幾個概念性問題:

  • 你只需要一個FlashCardPlayer視圖,它應該綁定下一個/上一個元素上的事件。 您可能應該有一個單獨的FlashCard視圖,它顯示一張卡片,玩家可以在按下下一個/上一個按鈕時交換這些視圖。 作為一般規則,如果你有一個帶有id的元素,你應該只渲染和綁定一次,使用單個視圖實例,否則你最終會遇到與現在相同的問題。

  • 您試圖在FlashCardPlayer模型中塞入太多內容。 通常,模型應該只知道它們的數據,而不是用於顯示它們的視圖(部分原因是一個模型可能需要在各種視圖中顯示)。 我不介意在模型上使用nextFlashCard()previousFlashCard()方法,因為這仍然在存儲有關集合的數據的領域,但showCard()方法確實正在直接進入視圖領域,因為它處理與呈現邏輯。 一個更好的主意是讓您的視圖綁定到模型上的change:currentCardIndex事件並處理新卡的顯示,使用this.model.get('currentCardIndex')) (或新的getCurrentCard()方法)為拿到它,為實現它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM