我坚持以下问题:
我有一个带有属性的模型,该属性定义它是否被明显选择,为了这个问题,我将调用SelectModel。
SelectModel = Backbone.Model.extend({
defaults:{
isSelected: false
}
})
现在,我真正得到的第一部分是我应该如何处理选择。 如果我想使用观察者模式,我的视图应该监听isSelected属性的更改。但我的观点也首先触发了这一点,所以我会这样做。
SelectView = Backbone.View.extend({
initialize: function(){
this.model.bind("change:isSelected", this.toggleSelectionVisually)
},
events: {
"click" : toggleSelection
},
toggleSelection: function(){
this.model.set({"isSelected": !this.model.get("isSelected");
},
toggleSelectionVisually:(){
//some code that shows that the view is now selected
},
})
所以这本身已经感觉有点荒谬,但我想我只是理解错误。
但是,如果不使我的代码变得非常糟糕,我真正无法实现的部分是处理多个模型的选择,一次只选择一个模型。
SelectListView = Backbone.View.extend({
initialize: function(){
this.collection = new SelectList();
},
toggleSelection: function(){
????
}
})
那么谁应该通知谁选择更改?哪个部分应该触发它,哪个部分应该听?我真的被困在这一个。对于单个视图来说,这是可行的,因为我很遗憾地丢失了一个集合。
答案 0 :(得分:3)
在我看到你问题的第二部分之前,我会为你的SelectView
建议以下简化:
SelectView = Backbone.View.extend({
events: {
"click" : toggleSelection
},
toggleSelection: function(){
this.model.set({"isSelected": !this.model.get("isSelected");
//some code that shows whether the view is selected or not
}
});
但是,由于isSelected
属性显然是互斥的,因此可以在切换另一个属性时隐式切换,我认为你拥有它的方式最适合你的情况。
因此,使用现有的SelectView
,您可以拥有SelectListView
,如下所示。 警告:每次选择一个模型时,它会遍历整个模型集合。如果你有大量的模型,这将无法很好地扩展,你将需要缓存先前选择的模型,而不是迭代整个集合。
SelectListView = Backbone.View.extend({
initialize: function(){
this.collection = new SelectList();
this.collection.bind('change:isSelected', this.toggleSelection, this);
},
toggleSelection: function(toggledModel){
//A model was toggled (on or off)
if(toggledModel.get('isSelected') {
//A model was toggled ON, so check if a different model is already selected
var otherSelectedModel = this.collection.find(function(model) {
return toggledModel !== model && model.get('isSelected');
});
if(otherSelectedModel != null) {
//Another model was selected, so toggle it to off
otherSelectedModel.set({'isSelected': false});
}
}
}
});
答案 1 :(得分:3)
我建议你的模型不要跟踪这个,而是视图。
在我看来,模型与其显示无关,而是与您正在跟踪的数据无关。视图应该封装有关数据在何处以及如何显示给用户的所有信息
所以我会将isSelected
作为属性放在视图上。然后编写一个切换可见性的方法是微不足道的。如果您需要解释选择特定视图的其他视图,您可以附加一个监听器$(this.el).on('other_visible', toggle_show)
,您可以使用toggle_visibility
$(this.el).trigger('other_visible')
方法上触发该监听器
答案 2 :(得分:2)
非常接近@rrr建议的解决方案,但是将逻辑从View
移到Collection
,我认为它可以反映到:
SelectsCollection = Backbone.Collection.extend({
initialize: function() {
this.on( "change:selected", this.changeSelected );
},
changeSelected: function( model, val, opts ){
if( val ){
this.each( function( e ){
if( e != model && e.get( "selected" ) ) e.set( "selected", false );
});
};
},
});
答案 3 :(得分:0)
有不同的方法可以做到这一点。您可以在集合本身上触发事件,并让所有SelectModel实例监听它并相应地更新自己。如果你在集合中有很多SelectModel实例,那似乎有点浪费,因为大多数实例都不会做任何工作。我可能会做的是跟踪视图中的最后一个SelectModel:
SelectListView = Backbone.View.extend({
initialize: function(){
this.collection = new SelectList();
this.lastSelectedModel = null;
},
toggleSelection: function(){
// populate newSelectedModel with the SelectedModel that you're toggling
var newSelectedModel = getNewSelectedModel();
if (!newSelectedModel.get('isSelected')) {
// if the SelectModel isn't already selected, we're about to toggle it On
// so we need to notify the previously selected SelectModel
if (this.lastSelectedModel) {
this.lastSelectedModel.set({isSelected: false});
}
this.lastSelectedModel = newSelectedModel;
} else {
// if the newSelectedModel we're about to toggle WAS already selected that means
// nothing is selected now so clear out the lastSelectedModel
this.lastSelectedModel = null;
}
newSelectedModel.set({isSelected: !newSelectedModel.get('isSelected')});
}
})