我正在尝试找到一种方法来有效地显示已排序的Marionette.CollectionView,按多个属性排序,而不修改底层的Backbone集合。对于此示例,我使用'name'和'online'属性,并希望我的CollectionView分为两部分显示:
我有一个Backbone.Model集合,并希望在我的Web应用程序中使用它。所以在我的Collection上使用sort函数对我来说感觉不对。
我的示例代码如下:
var MyCollection = Backbone.Collection.extend({
model:Backbone.Model
});
var myCollection = new MyCollection();
myCollection.set([
{ name : 'Freddy', online : true },
{ name : 'Zorro', online : false },
{ name : 'Charlie', online : false },
{ name : 'Alice', online : true }
]);
var MyView = ...
/*
omitted for brevity, though my template is like
<li>{{name}} {{#if online}}(Online){{/if}}</li>
*/
var MyCollectionView = Marionette.Collection.extend({
childView:MyView,
viewComparator: function (item1, item2) {
var item1Online = item1.get('online');
var item2Online = item2.get('online');
if (item1Online != item2Online)
return item1Online ? -1 : 1;
var item1Name = item1.get('name');
var item2Name = item2.get('name');
return item1Name.localeCompare(item2Name);
}
});
var myCollectionView = new MyCollectionView({collection:myCollection});
appView.getRegion('example').show(myCollectionView);
我希望将其显示为:
将所有数据一次添加到集合中,或者添加/删除事件但是如果在已经在集合中的模型上更新其中一个属性,则视图不会更新。
如果查理的“在线”属性改为真实 - 例如通过表演。
charlieModel.set('online', true)
我希望CollectionView自动呈现为:
有什么建议吗?非常感谢提前。
答案 0 :(得分:1)
如果稍后更改模型属性,使用比较器的集合将不会自动重新排序,因此您可能希望在更改会影响订单的模型属性后调用sort。
您可以在代码中的某个位置放置一个侦听器,以更改您的目标模型属性,从而触发对您的集合进行重新排序。
// for example in your collection
initialize: function() {
this.on('change:name', function() { this.sort() }, this);
}
答案 1 :(得分:0)
Marionette团队建议在幕后使用单独的Backbone集合,而不是使用viewComparator
上的CollectionView
。
在CollectionView
上使用reorderOnSort在渲染速度方面产生了巨大的差异(至少提高了10倍)。
当您使用CollectionView时遇到性能问题时,此选项很有用。 如果没有此选项,您的CollectionView将完全重新呈现,即可 如果您有大量元素或者您的ChildViews很复杂,则代价很高。如果这个选项 激活,当您对Collection进行排序时,将不会重新呈现,只有DOM节点 将被重新订购。
我的最终示例代码:
var MyView = Backbone.Marionette.ItemView.extend({
modelEvents:{
'change:name change:online': 'render'
},
template:template
});
var MyCollection = Backbone.Collection.extend({
initialize : function(){
this.on('change:name change:online', this.sort, this);
},
comparator : function(item1, item2){
var item1online = item1.get('online');
var item2online = item2.get('online');
if (item1online != item2online)
return item1online ? -1 : 1;
return item1.get('name').localeCompare(item2.get('name'));
}
});
var myCollection = new MyCollection();
var MyCollectionView = Marionette.CollectionView.extend({
childView : MyView,
reorderOnSort : true
});
var myCollectionView = new MyCollectionView({
collection : myCollection
});
appView.region('example').show(myCollectionView);