使用CollectionView创建同级项目视图

Create Sibling ItemViews with a CollectionView?

本文关键字:项目 视图 CollectionView 创建 使用      更新时间:2023-09-26

我有一个backline.marionette应用程序,它正在使用CollectionView输出以下内容:

  • div#main.widget
    • div.head
    • div.body

以下是2个同级ItemViews:

var LogLocationBodyView = App.ItemView.extend({
    tagName: "div",
    attributes: {class: "body"},
    template: "#log-location-body-template"
});
var LogLocationHeadView = App.ItemView.extend({
    tagName: "div",
    attributes: {class: "head"},
    template: "#log-location-head-template" 
});

这是收藏视图:

var LogLocationsView = App.CollectionView.extend({
    template: "#log-locations-template",
    attributes: {id: "main", class: "widget"},
    itemView: LogLocationHeadView
});

我显然可以让LogLocationHeadView进行渲染,但我正在寻找inserAfter()LogLocationBodyView的最佳方法,这样这两个ItemView就是兄弟。

实现这一目标的最佳方法是什么?我尝试了许多不同的方法。首先,我尝试使用ItemView的onRender(),但很快意识到我只能附加到视图中的标记。我真的需要insertAfter(),而parent不可用,因为在onRender中,我们仍然是DOM插入之前。

var LogLocationHeadView = App.ItemView.extend({
    tagName: "div",
    attributes: {class: "head"},
    template: "#log-location-head-template",
    onRender: function() {
        // create a new piece of html from a different template
        var view = new LogLocationBodyView({
            model: this.model
        });
        view.render();
        $(this.el).append(view.el);
        var c = $(this.el).children();
            console.log(c); // true
        var p = $(this.el).parents();
            console.log(p); //undefined
    }

我也知道我可以覆盖CollectionViews中的appendHTML()和renderItem()方法,但我仍然需要能够append()。所以我需要能够传递renderType。

我真正想做的是将ItemViews数组和renderType一起传递给renderItem。然后,renderItems可以在appendHTML()中分叉。

var LogLocationsView = App.CollectionView.extend({
    template: "#log-locations-template",
    attributes: {id: "main", class: "widget"},
    itemViews: [{view: LogLocationHeadView, renderType: append}, {view: LogLocationBodyView, renderType: insertAfter}]
});

在我尝试这么做之前,我想看看我在这里是否完全偏离了底线。有更好的方法吗?

实现这一点的最佳和最干净的方法是让头部视图和主体视图的父视图在其render方法中同时附加这两个视图,而不必依赖insertAfter。如果您想从尚未插入但将处于当前浏览器事件循环末尾的视图处理它,您可以使用下划线defer方法或setTimeout(fn,1)方法将视图插入推迟到下一个循环。

顺便说一句,如果tagName是div,则不需要指定它,因为div是tagName的默认值。

这个问题从这里开始得到了回答:https://github.com/marionettejs/backbone.marionette/issues/36.在这里:https://github.com/marionettejs/backbone.marionette/issues/35

现在它是一个完整的功能:

http://lostechies.com/derickbailey/2012/04/05/composite-views-tree-structures-tables-and-more/