javascript - Backbone - 如何重构此代码以防止重影 View ?

标签 javascript backbone.js backbone-events

我有一组与 Backbone 集合相关的闪存卡集合。获得集合后,我将创建一个玩家模型的实例。

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

不幸的是,这种设计会导致每次单击下一个和上一个按钮事件时都会绑定(bind)它们。因此,例如,在第一次单击“下一个”按钮后,该事件将开始多次触发。我在某处读到过有关幽灵 View 的内容,但无法确切地弄清楚如何将下面的代码分解成一个 block ,以帮助我防止幽灵 View 问题。

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 的新实例。这些实例中的每一个都执行自己的事件处理,因此每个实例都绑定(bind)到相同的 #next#previous 元素。

我认为这里存在几个概念问题:

  • 您只需要一个 FlashCardPlayer View ,该 View 应将事件绑定(bind)到下一个/上一个元素上。您可能应该有一个单独的 FlashCard View ,它显示单张卡片,并且玩家可以在按下下一个/上一个按钮时将这些 View 换入和换出。作为一般规则,如果您有一个带有 id 的元素,您应该只使用单个 View 实例渲染和绑定(bind)到它一次,否则您最终会遇到与现在相同的问题。

  • 您试图在 FlashCardPlayer 模型中塞入太多内容。通常,模型应该只了解它们的数据,而不了解用于显示它们的 View (部分原因是一个模型可能需要在多种 View 中显示)。我不介意在模型上使用 nextFlashCard()previousFlashCard() 方法,因为这仍然属于存储有关集合的数据的范围,但是 showCard() 方法确实进入了 View 领域,因为它处理表示逻辑。更好的想法是让您的 view 绑定(bind)到模型上的 change:currentCardIndex 事件,并使用 this.model 处理新卡的显示.get('currentCardIndex'))(或新的 getCurrentCard() 方法)来获取它。

关于javascript - Backbone - 如何重构此代码以防止重影 View ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9866057/

相关文章:

javascript - Backbone js 并使用 fetch() 用数据填充模型

javascript - 使用 Backbone 的 Fetch() 发出 AJAX 请求时如何访问 XHR 对象?

javascript - Collection 在 Backbone 中添加事件监听器

JavaScript .click() 无意中自动启动

javascript - 如何使用 Vue.js 将事件类添加到选项卡动态创建的导航中?

jquery-mobile - 将 Backbone Boilerplate 与 jQuery Mobile 集成并放置布局结构

javascript - Google Maps JS v3 和 HTML5 JavaScript 框架

javascript - 无法通过 https 读取未定义的属性 'getusermedia'

javascript - IE9 onclick Bug?

backbone.js - 如何找到与点击的项目对应的模型ID?