【问题标题】:Grouped collection and views with Backbone.Marionette使用 Backbone.Marionette 分组集合和视图
【发布时间】:2014-10-30 01:53:03
【问题描述】:

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

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

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

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

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

【问题讨论】:

  • 我不认为有任何本地方法可以自动更新您的 groupBy,因为 Backbone 并没有真正使用它(我想说这种方法更多是出于礼貌添加)。
  • 我也这么认为。我在想我可以使用 groupBy 创建更小的、基于月份的集合并为它们使用 CompositeView。我想知道再次运行 groupBy 并从组中重置基于月份的集合是否会重新呈现整个视图或仅更新更改的内容?
  • 我对 Marionette 了解不多,对你的应用程序的精确结构也不太了解,所以我不能说太多。我认为您的问题过于针对具体情况。

标签: backbone.js marionette


【解决方案1】:

我想了很多,但没有一个完美的答案,但这里是我的笔记(脑力转储),以防它们帮助/激发任何新想法:

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

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

当我第一次加入当前团队时,他们有一些实现选项 1B 的旧代码,我认为这很糟糕。然后,当我必须实现类似的东西时,我选择了选项 3,它有效,但随着时间的推移变得有点混乱。下次我想我会尝试选项 1A,但目前尚未测试...

告诉我你最后做了什么!

编辑:Github 上 Marionette 项目的几个相关问题:

【讨论】:

    【解决方案2】:

    您可以创建一个新的 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);
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-25
      相关资源
      最近更新 更多