Backbone可以以相反的顺序呈现集合吗?

时间:2012-03-19 12:19:52

标签: backbone.js marionette

我正在使用Signalr中心订阅服务器上的事件。什么事件被分派到集线器,它成功地将项目添加到Marionette CollectionView。反过来,这会呈现给一个表格。

因为事件表本质上是一个吸墨纸,我希望这些事件的顺序相反,最好只保留n个事件。

Backbone可以“自动”以相反的顺序重新呈现集合吗?

8 个答案:

答案 0 :(得分:11)

要按相反的顺序进行收集,我通常使用这样的结构:

_.each(collection.last(collection.length).reverse(), function(model){ });

答案 1 :(得分:8)

https://github.com/marionettejs/backbone.marionette/issues/78

上有关于此主题的主题

虽然Backbone在定义比较器后对集合进行了排序,但正如@breischl所指出的那样,当订单发生变化时,Marionette不会自动重新渲染CollectionView。实际上,Marionette会收听集合上的add事件,会附加一个新的ItemView。

如果您希望CollectionView始终按相反的时间顺序显示项目,并且您希望添加新项目预先而不是追加,则覆盖appendHtml中的CollectionView方法如下:

var MyCollectionView = Backbone.Marionette.CollectionView.extend({
  appendHtml: function(collectionView, itemView){
    collectionView.$el.prepend(itemView.el);
  }
});

如果您希望能够在评论中提到的@dira中插入特定位置,那么在sberryman的github上面的链接上发布了一个解决方案,为了方便我在这里重现(免责声明:我还没有测试过以下代码:

将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);

答案 2 :(得分:1)

通常,您将在Backbone.View'子类'中进行渲染。所以你有类似的东西:

render: function() {
  this.collection.each( function(model) {
    // some rendering of each element
  }, this );
}

this.collection大概是一个Backbone.Collection子类,因此您可以在其上使用underscore.js methods以您喜欢的顺序获取它:

this.collection.reverse().each( ... )
this.collection.sort( function(m) { ... } ).each( ... )

当然,您从后端获取单个元素,并且希望将其插入正确的位置而无需重新渲染整个元素!因此,在这种情况下,只需去旧学校并在元素上插入排序键作为rel属性或data属性,并在{{1}中将其用于insertAfter或类似jQuery (或类似的)方法。

答案 3 :(得分:1)

Backbone会自动按照排序顺序保存集合。如果要使用非默认排序,请在集合中定义comparator()函数,它将使用该函数。比较器可以采用一个或两个参数see the Backbone documentation来获取详细信息。

然后,您可以在.each()循环中渲染您的集合,它将以正确的顺序出现。但是,按排序顺序向视图添加新项目取决于您自己。

答案 4 :(得分:1)

根据您的描述,您无需以相反的顺序重新呈现集合。只需在该视图中为您的集合添加add的事件,并让它调用一个函数,该函数只是添加项目并将其预先添加到表格中。

this.collection.on('add', this.addItem);

答案 5 :(得分:0)

您可以在类似的集合中反转模型......

this.collection.models = this.collection.models.reverse()

答案 6 :(得分:0)

如果您使用lodash而不是下划线,您也可以这样做:

_(view.collection.models).reverse();

答案 7 :(得分:0)

由于BackBone不支持集合的反向迭代(并且它只是浪费资源来反转或更糟糕地对集合进行排序),最简单快速的方法是使用for循环使用集合中模型的索引递减。

for (var i = collection.length - 1; i >= 0; i--) {
    var model = collection.models[i];

    // your logic
}

使用Underscore排序或反转集合并不是那么优雅,但性能要好得多。尝试比较不同的循环here只是为了知道你为foreach写的是什么成本而不是经典的。