如何在Backbone Marionette中显示具有多个子视图的CompositeView

时间:2013-09-08 22:12:52

标签: javascript backbone.js marionette

启动问题

我有一个CompositeView(一个表),集合中的每个模型都表示为两个表行,其模板如下:

<tr class="row-parent">
    <td>parent info here</td>
</tr>
<tr class="row-child">
    <td>child info here</td>
</tr>

使用这样的ItemView:

var ItemView = Backbone.Marionette.ItemView.extend({
    template: ItemTmpl
});

即使它们被命名为“父”和“孩子”,它们实际上也是同一模型的同伴成员。如果我没有指定tagName,Backbone将在<div>中包装每个视图,这两个视图都是无效的HTML并且也会破坏布局。

解决方案的第一次尝试

所以我想,为什么不删除外部<tr>标签并让Backbone添加它们。所以我将模板更新为:

    <td>parent info here</td>
</tr>
<tr class="row-child">
    <td>child info here</td>

并将视图更新为:

var ItemView = Backbone.Marionette.ItemView.extend({
    template: ItemTmpl,
    tagName: 'tr',
    className: 'row-parent'
});

我希望外部标签与内部标签碎片结合,但是Marionette并不喜欢这样。它只显示了行子。所以我不确定从哪里开始。我正在考虑两种策略,但还没有详细介绍。

前进:计划A

覆盖Backbone的任何部分创建额外的div而不创建它,或覆盖Marionette的一部分,该部分附加视图以在追加之前删除div。

前进:计划B

创建一种名为CompositeMultiView的新类型的视图,当然,它将扩展CompositeView,并允许您指定第二个ItemView,或者只是一个视图数组,所有这些视图都会为给定的每个模型呈现。这个计划似乎更多的工作,但更少被黑客攻击。


有没有人有更好的建议,解决方法或具体指示我将如何实施上述两个计划中的任何一个?

这是表格应该是什么样子的模型: enter image description here

3 个答案:

答案 0 :(得分:4)

我一直在努力解决同样的问题,直到我今天终于发现,一个表可以包含多个tbody标记,每个标记包含多个tr标记。

这实际上是the answer提供给类似的骨干问题。

所以你的ItemView会变成:

var ItemView = Backbone.Marionette.ItemView.extend({
    template: ItemTmpl,
    tagName: 'tbody'
});

生成的html:

<table>
  <!-- first item -->
  <tbody>
    <tr class="row-parent">
      <td>parent info here</td>
    </tr>
    <tr class="row-child">
      <td>child info here</td>
    </tr>
  </tbody>
  <!-- second item -->
  <tbody>
    <tr class="row-parent">
      <td>parent info here</td>
    </tr>
    <tr class="row-child">
      <td>child info here</td>
    </tr>
  </tbody>
  ...
</table>

答案 1 :(得分:1)

您可以尝试按如下方式修改CompositeView:

  1. itemView指定为视图数组
  2. 覆盖addChildView以呈现每个模型的每个视图
  3. 此解决方案最终看起来很像“B计划”。试一试:

    itemView: [My.ParentView, My.ChildView],
    
    addChildView: function(item, collection, options){
      this.closeEmptyView();
      var itemViews = this.getItemView(item);
      var index = this.collection.indexOf(item);
    
      _.each(itemViews, function(ItemView) {
        this.addItemView(item, ItemView, index);
      });
    }
    

    我没有想过这是否会处理destroy之类的模型事件,但我相信它应该优雅地处理它们。

答案 2 :(得分:0)

脏解:向ItemView添加自定义渲染功能

// Or whatever template you use
var template = Handlebars.compile(datepickerTemplate);

var ItemView = Backbone.Marionette.ItemView.extend({
    render: function(){
        var html = template(this.model.toJSON());
        var newElement = $(html);
        this.$el.replaceWith(newElement);
        this.setElement(newElement);
        return this;
    }
});

这应该删除额外的div包装