我正在使用 Signalr 集线器订阅服务器上的事件。将什么事件分派到集线器,它成功地将项目添加到 Marionette CollectionView。反过来,这会呈现到表格中。
因为事件表本质上是一个吸墨纸,所以我希望事件以相反的顺序排列,最好只保留 n 个事件。
Backbone 可以“自动”以相反的顺序重新渲染集合吗?
我正在使用 Signalr 集线器订阅服务器上的事件。将什么事件分派到集线器,它成功地将项目添加到 Marionette CollectionView。反过来,这会呈现到表格中。
因为事件表本质上是一个吸墨纸,所以我希望事件以相反的顺序排列,最好只保留 n 个事件。
Backbone 可以“自动”以相反的顺序重新渲染集合吗?
为了以相反的顺序进行收集,我通常使用这样的结构:
_.each(collection.last(collection.length).reverse(), function(model){ });
在https://github.com/marionettejs/backbone.marionette/issues/78上有一个关于此主题的主题
正如@breischl 指出的那样,尽管 Backbone 在定义比较器后会保持集合的排序,但当订单更改时,Marionette 不会自动重新渲染 CollectionView。事实上,Marionette 会监听add
集合上的事件并附加一个新的 ItemView。
如果您希望CollectionView
始终以相反的时间顺序显示项目,并且希望添加的新项目被添加而不是appended,然后覆盖您的方法,如下所示:appendHtml
CollectionView
var MyCollectionView = Backbone.Marionette.CollectionView.extend({
appendHtml: function(collectionView, itemView){
collectionView.$el.prepend(itemView.el);
}
});
如果您希望能够像评论中提到的@dira 那样在特定位置插入,sberryman 在上面的链接中发布了一个解决方案,为了方便起见,我在此处复制了该解决方案(免责声明:我没有测试下面的代码亲自):
将 appendHtml 更改为:
appendHtml: function(collectionView, itemView) {
var itemIndex;
itemIndex = collectionView.collection.indexOf(itemView.model);
return collectionView.$el.insertAt(itemIndex, itemView.$el);
}
并添加以下内容以扩展jQuery
以提供insertAt
功能:
(function($) {
return jQuery.fn.insertAt = function(index, element) {
var lastIndex;
if (index <= 0) return this.prepend(element);
lastIndex = this.children().size();
if (index >= lastIndex) return this.append(element);
return $(this.children()[index - 1]).after(element);
};
})(jQuery);
通常你会在你Backbone.View
的“子类”中进行渲染。所以你有类似的东西:
render: function() {
this.collection.each( function(model) {
// some rendering of each element
}, this );
}
this.collection
大概是一个Backbone.Collection
子类,因此您可以在其上使用underscore.js 方法以您喜欢的任何顺序获取它:
this.collection.reverse().each( ... )
this.collection.sort( function(m) { ... } ).each( ... )
等等。
当然,您从后端获取单个元素,并且您希望将其插入正确的位置,而无需重新渲染整个内容!因此,在这种情况下,只需回到旧学校并将您的排序键作为rel
属性或data
属性插入元素,并在您的(或类似的)方法中使用它insertAfter
或与 jQuery类似。renderNewItem
Backbone 自动将 Collections 保持在排序顺序。如果您想使用非默认排序,comparator()
请在您的 Collection 上定义一个函数,它将使用该函数。比较器可以采用一个或两个参数,有关详细信息,请参阅 Backbone 文档。
然后,您可以在 .each() 循环中呈现您的集合,它会以正确的顺序出现。不过,按排序顺序将新项目添加到视图中取决于您。
根据您的描述,您不需要以相反的顺序重新渲染集合。只需在该视图中为您的集合添加一个事件,add
并让它调用一个函数,该函数呈现刚刚添加的项目并将其添加到表中。
this.collection.on('add', this.addItem);
如果你使用lodash而不是下划线,你也可以这样做:
_(view.collection.models).reverse();
您可以像这样在集合中反转模型...
this.collection.models = this.collection.models.reverse()
由于 BackBone 不支持集合的反向迭代(并且对集合进行反向或更糟糕的排序只是浪费资源),因此最简单和最快的方法是for
在集合中的模型上使用具有递减索引的循环。
for (var i = collection.length - 1; i >= 0; i--) {
var model = collection.models[i];
// your logic
}
它不像使用下划线对集合进行排序或反转那样优雅,但性能要好得多。尝试在这里比较不同的循环,以了解您编写 foreach 而不是经典 for 的成本。