Marionette CompositeView作为itemView的自己的itemView(循环递归?)

时间:2014-02-05 23:24:10

标签: backbone.js twitter-bootstrap-3 marionette

这是一个有趣的。我有两个CompositeViews,CategoriesViewCategoryView,我有一个嵌套的类别集合,其中每个类别可能有0个或更多子节点。我想渲染该集合,以便任何有孩子的类别都使用CategoriesView作为itemView和任何不使用CategoryView的类别。理想情况下,我希望CategoryView使用CategoriesView作为itemView,反之亦然。所以:

+---------------------------------+
| CategoriesView: Title           | <- 4 children
|---------------------------------|
| CategoryView: item 1            | <- 0 children
| CategoryView: item 2            | <- 0 children
| CategoryView: item 3            | <- 0 children
| +-----------------------------+ |
| | CategoriesView: title       | | <- 10 children
| |-----------------------------| |
| | CategoryView: item 5        | |
...

我遇到的问题是我无法将CategoryView的{​​{1}}属性定义为itemView,因为该对象稍后在脚本文件中定义。这会导致CategoriesView将自己用作CompositeView

itemView

(旁注:我正在使用Bootstrap的var CategoryView = Marionette.CompositeView.extend({ template: catTpl, tagName: 'li', itemView: CategoriesView, itemViewContainer: '.panel-group', initialize: function() { if (this.model.get('children').length) { this.collection = this.model.get('children'); } }, onRender: function() { if (!this.collection) { this.$(".panel-group").remove(); } } }); var CategoriesView = Marionette.CompositeView.extend({ template: groupTpl, className: "panel panel-default", itemView: CategoryView, itemViewContainer: '.panel-body ul', initialize: function() { this.collection = this.model.get('children'); } }); panel将每个类别组渲染为自己的面板。)

现在,它将顶级类别呈现为面板,将下面的所有内容呈现为列表。

有没有更好的方法来处理这种嵌套视图关系?我确信如果需要我可以一起破解,但我宁愿以“正确”的方式做到这一点。 :)或者我应该忘记它并通过在collapse上省略itemView来使用嵌套列表路线,以便它自己使用?

2 个答案:

答案 0 :(得分:1)

这应该有效:

var CategoryView = Marionette.CompositeView.extend({
    // don't define the itemView here...
});

var CategoriesView = Marionette.CompositeView.extend({
    // edited for brevity
    itemView: CategoryView,
    // edited for brevity
});

CategoryView.itemView = CategoriesView

答案 1 :(得分:0)

我最终做的是重写getItemView函数以返回相应的ItemView类:

// Renders a simple list item
var CategoryView = Marionette.CompositeView.extend({
    template: catTpl,
    tagName: "li"
});

// Renders a Panel with heading and body and container for list items
var CategoriesView = Marionette.CompositeView.extend({
    template: groupTpl,
    className: "panel panel-default",
    itemViewContainer: '.panel-body ul',
    // Reuse this as the itemView if we need to render a sub-list
    getItemView: function(item) {
        if (item.get('children').length == 0) {
            return CategoryView;
        } else {
            return this.constructor;
        }
    },
    initialize: function() {
        this.collection = this.model.get('children');
    }
});

// Renders the outermost container
return Marionette.CompositeView.extend({
    template: mainTpl,
    className: "carousel slide",
    attributes: {
        "data-interval": false,
        "data-wrap": false
    },
    itemView: CategoriesView,
    itemViewContainer: '#categories'
});

这非常有效,并且允许我有一个更复杂的布局,它不太适合CompositeViews开箱即用的传统树/叶模式。