多个属性的高效 Marionette 排序 CollectionView
Efficient Marionette sorted CollectionView for multiple attributes
我正在尝试找到一种方法来有效地显示按多个属性排序的 Marionette.CollectionView,而无需修改基础 Backbone collection.对于这个例子,我使用 'name' 和 'online' 属性,并希望我的 CollectionView 分两部分显示:
- 在线,按字母顺序
- 离线,按字母顺序
我有一个 Collection of Backbone.Models 并且想在我的网络应用程序中使用它。所以在我的 Collection 上设置排序功能对我来说并不合适。
我的示例代码如下:
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);
我希望它显示为:
- 爱丽丝(在线)
- 弗莱迪(在线)
- 查理
- 佐罗
当所有数据一次添加到 collection 或 add/remove 事件时,这很好,但是如果在 [=] 中已经存在的模型上更新其中一个属性65=],视图不更新。
如果查理的 'online' 属性 更改为 true - 例如通过执行。
charlieModel.set('online', true)
我希望 CollectionView 自动呈现为:
- 爱丽丝(在线)
- 查理(在线)
- 弗莱迪(在线)
- 佐罗
有什么建议吗?非常感谢。
Collections with a comparator will not automatically re-sort if you later change model attributes, so you may wish to call sort after changing model attributes that would affect the order.
您可以在代码中方便的地方放置一个侦听器,以侦听您所针对的模型属性的变化,这将触发对您的集合进行重新排序。
// for example in your collection
initialize: function() {
this.on('change:name', function() { this.sort() }, this);
}
Marionette 团队建议在幕后有一个单独的 Backbone 集合,而不是在 CollectionView
上使用 viewComparator
。
在 CollectionView
上使用 reorderOnSort 在渲染速度方面产生了巨大的差异(至少加速了 10 倍)。
This option is useful when you have performance issues when you resort your CollectionView.
Without this option, your CollectionView will be completely re-rendered, which can be
costly if you have a large number of elements or if your ChildViews are complex. If this option
is activated, when you sort your Collection, there will be no re-rendering, only the DOM nodes
will be reordered.
我的最终示例代码:
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);
我正在尝试找到一种方法来有效地显示按多个属性排序的 Marionette.CollectionView,而无需修改基础 Backbone collection.对于这个例子,我使用 'name' 和 'online' 属性,并希望我的 CollectionView 分两部分显示:
- 在线,按字母顺序
- 离线,按字母顺序
我有一个 Collection of Backbone.Models 并且想在我的网络应用程序中使用它。所以在我的 Collection 上设置排序功能对我来说并不合适。
我的示例代码如下:
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);
我希望它显示为:
- 爱丽丝(在线)
- 弗莱迪(在线)
- 查理
- 佐罗
当所有数据一次添加到 collection 或 add/remove 事件时,这很好,但是如果在 [=] 中已经存在的模型上更新其中一个属性65=],视图不更新。
如果查理的 'online' 属性 更改为 true - 例如通过执行。
charlieModel.set('online', true)
我希望 CollectionView 自动呈现为:
- 爱丽丝(在线)
- 查理(在线)
- 弗莱迪(在线)
- 佐罗
有什么建议吗?非常感谢。
Collections with a comparator will not automatically re-sort if you later change model attributes, so you may wish to call sort after changing model attributes that would affect the order.
您可以在代码中方便的地方放置一个侦听器,以侦听您所针对的模型属性的变化,这将触发对您的集合进行重新排序。
// for example in your collection
initialize: function() {
this.on('change:name', function() { this.sort() }, this);
}
Marionette 团队建议在幕后有一个单独的 Backbone 集合,而不是在 CollectionView
上使用 viewComparator
。
在 CollectionView
上使用 reorderOnSort 在渲染速度方面产生了巨大的差异(至少加速了 10 倍)。
This option is useful when you have performance issues when you resort your CollectionView. Without this option, your CollectionView will be completely re-rendered, which can be costly if you have a large number of elements or if your ChildViews are complex. If this option is activated, when you sort your Collection, there will be no re-rendering, only the DOM nodes will be reordered.
我的最终示例代码:
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);