[英]How to prevent multiple even firings with recursive Backbone.js views?
[英]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.