2012-03-19 134 views
7

我正在使用Signalr集线器订阅服务器上的事件。什么事件发送到集线器,它成功地将项目添加到木偶集合视图。这反过来又呈现为一张表格。Backbone可以以相反的顺序渲染一个集合吗?

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

可以骨干'自动'以相反的顺序重新呈现集合?

回答

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属性,并在renderNewItem(或类似)方法中使用insertAfter或类似的jQuery。

+2

不幸的是,reverse()方法在underscore.js方法中可用。 – hbruce 2012-05-31 09:35:54

+0

哈哈好点!不过,我的答案并不是真正的基石。你可以使用不同的方法来反转它:'_.each(_.toArray(this.collection).reverse(),function(m){...});'。或者,如果你使用咖啡脚本,你可以用-1步写一个for循环,等等。 – rfunduk 2012-06-04 13:38:45

1

骨干自动保持集合的排序顺序。如果要使用非默认排序,请在您的集合上定义一个comparator()函数,然后它将使用该函数。有关详细信息,比较器可以采用一个或两个参数,即see the Backbone documentation

然后,您可以在.each()循环中呈现您的集合,并且它会以正确的顺序出现。不过,按照排序顺序向视图添加新项目取决于您。

+0

Dira,好点,它确实使它更容易。但最终你还是得把它们放到正确的位置上。 – 2012-03-20 14:47:09

+1

是的,所以你使用jquery的第n个孩子,之后()或之前() – dira 2012-03-20 21:18:27

1

从您所描述的内容中,您不需要按相反顺序重新呈现集合。只需在该视图中为您的收藏集添加一个add的事件,并让它调用一个函数来呈现刚刚添加的项目并将其预先添加到表格中。

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

有一个在https://github.com/marionettejs/backbone.marionette/issues/78

有关这个主题的一个线程尽管骨干不断的收集整理,一旦你定义了一个比较,因为@breischl指出,木偶不会自动重新渲染的CollectionView当订单变更。实际上,Marionette收集了add事件,附加了一个新的ItemView。

如果你希望你的CollectionView始终显示在反向时间顺序的项目,并希望新的项目加入到被前置而不是附加,然后重写appendHtml方法在CollectionView如下:

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

如果你想能够插入特定的位置作为评论中提到的@dira,在sithman的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); 
+1

请注意,在Marionette 2.x中,appendHtml已更改为attachHtml。希望能帮助别人!这正是我需要以相反的顺序显示集合,而不会在我的Web应用程序中混淆其他逻辑的顺序 – mix3d 2015-04-20 18:47:38

11

要经过收集以相反的顺序我通常使用一个建筑是这样的:

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

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

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

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

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

为骨干,不支持收集的反向迭代(它只是浪费资源对集合进行反转或更差的排序)最简单且最快的方法是使用for循环,该集合中的模型索引减少。

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

    // your logic 
} 

这并不像使用Underscore对集合进行排序或反转一样优雅,但性能要好得多。尝试比较不同的循环here只是要知道什么花费你写foreach而不是经典的。