使用Backbone.Marionette分组收集和查看

时间:2013-04-09 06:33:19

标签: backbone.js marionette

我有一个Backbone文档集合,我希望按月分组,以便在同一个月内创建的所有文档组合在一起。我知道我基本上可以通过以下方式实现这一目标:

var byMonth = documents.groupBy(function(doc){
  return this.get('date').getMonth()
});

现在我有byMonth数组,设置骨干视图的最佳方法是什么,当项目添加到集合时,自动更新,其中一个文档的日期更改等等 - 这样文档将自动移动到正确的组,并相应地更新视图?

PS。我还想显示每个月的汇总数据(例如,文档数量等)。

Marionette的CompositeView非常适合这类事物,但我不确定是否以及如何使其与分组集合一起使用?

2 个答案:

答案 0 :(得分:1)

我已经考虑了很多,并没有完美的答案,但这是我的笔记(脑力转储)以防他们帮助/激发任何新想法:

显示(并自动更新)分为3个部分/组的集合的最佳方式,例如本周,下周和即将到来的

  1. 在视图外部过滤集合:在Controller中创建过滤的子集合,并将一个集合传递给每个CollectionView。然后有2个选项用于修改集合:
    • A)直接修改3个子集合
      • Pro:自动更新将起作用,CollectionView中不需要过滤逻辑,emptyView将起作用,在每个部分的顶部都很容易计数。
      • Con:必须在我们可能想要修改它们的地方传递这3个集合,并在添加/删除事件时具有这个额外的逻辑:if (event.time<next-week) {...} else if (event.time<upcoming) {...} else {...}。可以将所有这些抽象为一个新实体,它已经引用了所有3个集合,并且具有包含上述逻辑的简单添加/删除方法。
      • 另一个问题:项目无法在这些子集合之间移动,如果分组是特定时间的,则这可能很关键。我想这只会在完全重新渲染时发生,所以你可以使用updateSubCollections方法并调用onBeforeRender或其他任何东西。
    • B)仅修改父集合 - 需要主集合上的侦听器,以便在添加/删除时手动重新过滤Controller中的每个子集合,并手动重新渲染所有3个列表视图。
      • Pro:CollectionView非常简单 - 没有过滤逻辑等,emptyView正常工作,很容易在每个部分的顶部进行计数。
      • Con:你失去了自动更新魔法(当一个集合发生变化时,它的collectionView会自动更新),并且每次都需要对整个collectionView进行愚蠢(代价高昂)的重新渲染
  2. 过滤View中的集合:将完整集合传递给每个CollectionView,并覆盖appendHTML方法(或showCollection)以仅显示满足条件的那些。
    • Pro:获取自动更新魔法,并且仍然只处理代码中的任何地方的单个集合
    • Con:需要额外的逻辑来显示每个部分顶部的计数。需要一些额外的逻辑来显示空视图,并且可能有其他后果,因为我怀疑CollectionViews是为此设计的...他们可能在后台使用所有项目视图做聪明的东西 - 它可能效率低 - 需要研究。查看源代码并找到最佳(最高级别)功能,以覆盖不打扰处理不相关的项目
  3. 单视图选项:通过手动附加页面右侧部分中的每个视图,在视图的appendHtml()函数中过滤集合。
    • Pro:一个地方的所有逻辑,但可能不是正确的地方(CollectionView)。自动更新有效。仍然只在代码处处理单个集合。
    • Con:需要额外的逻辑来显示每个部分顶部的计数。需要手动处理每个部分的emptyView,这不是很难 - 在你的模板中只定义所有部分,包含空消息,然后在你的appendHtml函数中,当你弄清楚该项属于哪个部分时,只需在追加该部分之前隐藏该部分的空消息。问题是如何在从集合中删除项目时隐藏空白部分。唯一的方法是监听集合中的remove事件,并检查所有部分以查看它们是否为空?或者只是重新渲染整个事物。
  4. 当我第一次加入我现在的团队时,他们有一些旧代码实现了选项1B,我觉得这很糟糕。然后,当我不得不实现类似的东西时,我选择了3,它有效,但随着时间的推移变得有些混乱。下次我想我会尝试选项1A,但目前尚未经过测试......

    让我知道你最终做了什么!

    编辑:关于Github上木偶项目的几个相关问题:

答案 1 :(得分:0)

您可以创建一个新的byMonth集合并绑定一个函数,以便在每次文档集合更改时重置它。

<强>控制器

App.Controller = function(){
  this.documents = new DocumentCollection();
  this.byMonthCollection = new ByMonthCollection(); 
  this.byMonthView = new ByMonthView({collection: this.byMonthCollection});
}

_.extend(App.Controller.prototype, {
  start: function() {
    this.documents.bind("change", _.bind(this.groupByMonth, this));
    this.documents.fetch();
  },
  groupByMonth: function() {
    var grouped = documents.groupBy(function(doc){
                    return this.get('date').getMonth() }); 

    this.byMonthCollection.reset(grouped);
  }
}