7

我正在使用骨干网和 marionette.js 构建一个应用程序。我计划使用集合视图来呈现一些项目,然后允许它们被过滤、排序和分组。

我想知道是否有任何好的设计理念可以以分组方式实际附加 html。我有一些想法,但我想知道是否有人可能会对哪个更好的设计提出意见。

我的第一个想法是更改集合视图上的 appendHtml 方法,如果启用了分组,我可以让 appendHtml 函数查找或创建子组的 bin 并将子视图放入其中。

appendHtml: function(collectionView, itemView, index){
  var $container = this.getItemViewContainer(collectionView);

  // get group from model
  var groupName = itemView.model.get("group");

  // try to find group in child container
  var groupContainer  = $container.find("." + groupName);

  if(groupContainer.length === 0){
    // create group container
    var groupContainer = $('<div class="' + groupName + '">')
    $container.append(groupContainer);
  }

  // Append the childview to the group
  groupContainer.append(itemView);
}

我的第二个想法是先将集合分成几组,然后可能会渲染多个视图……这个看起来可能工作量更大,但就代码结构而言也可能更好一些。

任何能引起意见的建议或想法都会很棒!

谢谢

4

3 回答 3

7

也许不完全是您正在寻找的东西,但这里有一个有点相关的问题:

Backbone.Marionette,网格中的收集项目(无表)

我对该问题的解决方案——一个可以呈现为列表或网格(“按行分组的项目”)的提取集合是在“包装器”CompositeView 中使用 _.groupBy() 并将修改后的数据传递到链中另一个 CompositeView(行),然后向下到一个 ItemView。

Views.Grid = Backbone.Marionette.CompositeView.extend({
    template: "#grid-template",
    itemView: Views.GridRow,
    itemViewContainer: "section",
    initialize: function() {
        var grid = this.collection.groupBy(function(list, iterator) {
            return Math.floor(iterator / 4); // 4 == number of columns
        });
        this.collection = new Backbone.Collection(_.toArray(grid));
    }
});

这是一个演示:

http://jsfiddle.net/bryanbuchs/c72Vg/

于 2013-02-13T15:59:34.513 回答
4

我已经完成了您建议的两件事,并且它们都运行良好。这在很大程度上取决于您更喜欢哪一种,也许哪一种更适合您的情况。

如果您的数据已经在分组层次结构中,使用许多分层模型/集合插件之一或您自己的层次结构代码,那么呈现组列表的想法可能更容易,每个组呈现项目列表。

如果您有平坦的数据,但包含一个您将分组的字段,那么 appendHtml 更改可能会更容易。

hth

于 2013-02-13T14:24:09.690 回答
1

这是对Derickbryanbuchs 的回答的补充。我的方法使用一个主集合视图和另一个集合视图作为它的子视图。

集合视图有一个“addChild”方法,每当模型添加到视图的集合中时都会调用该方法。'addChild' 方法负责渲染子视图并将其添加到 HTML 中,用于给定索引处的集合视图。你可以在这里查看 github 上的源代码。为了简化起见,我将其粘贴在这里:

addChild: function(child, ChildView, index) {
    var childViewOptions = this.getOption('childViewOptions');
    if (_.isFunction(childViewOptions)) {
      childViewOptions = childViewOptions.call(this, child, index);
    }

    var view = this.buildChildView(child, ChildView, childViewOptions);

    // increment indices of views after this one
    this._updateIndices(view, true, index);
    this._addChildView(view, index);
    return view;
}

如您所见,“addChild”方法调用了“buildChildView”方法。这个方法实际上构建了视图。

// Build a `childView` for a model in the collection.
buildChildView: function(child, ChildViewClass, childViewOptions) {
var options = _.extend({model: child}, childViewOptions);
return new ChildViewClass(options);
}

因此,对于您的用例,如果您的分组条件匹配,您可以覆盖“addChild”方法并调用原始方法。然后在重写的“buildChildView”方法中,您可以将组(它是您的集合的子集)传递给它的 childView,它是另一个 Marionette.CollectionView。

例子:

MyCollectionView.prototype.addChild = function(child, ChildView, index) {
    if(mycriteria){
        return ProductGroup.__super__.addChild.apply(this, arguments);
    }
};

MyCollectionView.prototype.buildChildView = function(child, ChildViewClass, 
childViewOptions) {

    options = _.extend({
        collection: "Pass your group collection which is a subset of your main collection"},
        childViewOptions
    );

    return new ChildViewClass(options);
  };
于 2014-09-05T13:54:50.277 回答