如何在项目之间呈现 Backbone collection 和 headers

How to render a Backbone collection with headers between items

我的应用程序中有一个 Backbone collection,它基本上是一个时间轴。 collection 中的每个项目都有一个 date 字段,collection 是按它排序的。项目被动态加载并添加到此 collection(当滚动时)。

我想渲染这个 collection,但我还需要在项目之间渲染一个 <div> 作为一天 header。示例:

[{"date": new Date("2015-01-02T12:00"),
  "text: "Message 4"},
 {"date": new Date("2015-01-02T06:00"),
  "text: "Message 3"},
 {"date": new Date("2015-01-01T23:00"),
  "text: "Message 2"},
 {"date": new Date("2015-01-01T20:00"),
  "text: "Message 1"}
]

我想渲染这样的东西:

<div class="timeline">
  <div class="day">2015-01-02</div>
  <div class="message">Message 4</div>
  <div class="message">Message 3</div>
  <div class="day">2015-01-01</div>
  <div class="message">Message 2</div>
  <div class="message">Message 1</div>
</div>

或者像这样(嵌套):

<div class="timeline">
  <div class="day">2015-01-02
    <div class="message">Message 4</div>
    <div class="message">Message 3</div>
  </div>
  <div class="day">2015-01-01
    <div class="message">Message 2</div>
    <div class="message">Message 1</div>
  </div>
</div>

我一直在查看 Backbone.Projections,但似乎我需要手动创建很多过滤的 collection(每天一个 collection),然后将所有那些每天 collection 变成另一个 collection.

我也看过 Backbone.Collection.groupBy,但我不知道如何使用它来呈现视图,更不用说如何在将新项目添加到时间轴时保持组更新了。

有没有好的方法来渲染这样的时间轴collection?有什么有用的插件吗?

Backbone 的优点之一是它不会强制您使用预定义的模式。在您的情况下,您可以按天对模型进行分组,为每个组生成 HTML,然后将结果推送到 DOM。

假设您的模型和集合是这样定义的,为方便起见:

var M =  Backbone.Model.extend({
    day: function() {
        var d = this.get('date'), 
            month = d.getMonth()+1,
            day = d.getDate();
        if (month<10) month = '0'+month;
        if (day<10) day = '0'+day;

        return [d.getFullYear(), month, day].join('-');
    }
});
var C = Backbone.Collection.extend({
    model: M
});

您的视图可能看起来像

var V = Backbone.View.extend({
    render: function() {
        var rows;

        rows = this.collection.chain().groupBy(function (m) {
            return m.day();
        }).map(function (models, dt) {
            // you would use a template here
            // hard coded strings will do for now

            var html = '<div class="day">' + dt + '</div>';
            _.each(models, function (m) {
                html+= '<div class="message">' + m.get('text') + '</div>';
            });

            return html;
        }).value();

        this.$el.html(rows.join(''));
    }
});

还有一个Fiddlehttp://jsfiddle.net/nikoshr/swbm8ax5/4/