Marionette CollectionView 在 collection.fetch 之后不是 re-rendering

Marionette CollectionView not re-rendering after collection.fetch

我有一个 'email' 风格的应用程序,可以显示按日期分组的消息。当应用程序加载时,浅层 collection 消息被提取并加载到 backbone collection 中。 collection 中的每个模型代表一个分组中的消息列表。 MessageGroup 表示一组消息,MessagesView 显示消息组。

这一切都很好,直到再次获取 collection 就像在应用过滤器之后一样,仅显示组 headers,而不显示其中的消息。我尝试触发 MessagesView 可以监听的事件,然后触发 re-render 本身,但我收到错误:listening.obj.off is not a function

var MessageModel = Backbone.Model.extend({});
var MessageCollection = Backbone.Collection.extend({
    model: MessageModel
});

var GroupModel = Backbone.Model.extend({});
var GroupCollection = Backbone.Collection.extend({
    model: GroupModel,
    url: '/messages/recipient',
    parse: function (response) {

        // Create a grouped JSON to render nested views with
        var messageArray = [];
        var groupedlist = _.groupBy(response.messages, function(model) {
            return model.publishDate;
        });

        _.forEach(groupedlist, function(n, key) {
            var grouping = {};
            grouping.group = key;
            grouping.list = n;
            messageArray.push(grouping);
        });

        return messageArray;
    },
    fetchMessages: function() {
        this.fetch({
            data: filtermodel.toJSON(),
            success: function() {

                var messagecollection = new MessageCollection();

                // Loop through each grouping and set sub-collections
                groupcollection.each(function(group) {
                    var list = group.get('list');

                    messagecollection.reset(list);
                    group.set('list', messagecollection);
                });
            }
        });
    }
});

// Model to track applied filters
var FilterModel = Backbone.Model.extend({
    defaults: {
        folder: 0
    }
});

// ------------------------  VIEWS  ------------- //

// View for a single Message
var MessageView = Backbone.Marionette.ItemView.extend({
    template: require('../../../templates/activities/message-item.ejs'),
    events: { 'click li.item': 'getMessageDetail' },
    getMessageDetail: function(e){
        this.triggerMethod('showDetail', this.model);
        //initMessageDetail(this.model);
    }

});

// Grouped container view for a list of Messages within a group
var MessageGroup = Backbone.Marionette.CompositeView.extend({
    template: require('../../../templates/activities/message-list.ejs'),
    className: "list-view-group-container",
    childView: MessageView,
    childViewContainer: "ul.viewcontainer",
    initialize: function() {
        this.collection = this.model.get('list');

    }

});

// Top level view for all grouped messages
var MessagesView = Backbone.Marionette.CollectionView.extend({
    childView: MessageGroup,
    initialize: function() {
        this.collection.on('change', this.log, this);
    },
    log: function() {
        console.log('triggered log');
    }
});

// View for selected message detail
var MessageDetailView = Backbone.Marionette.ItemView.extend({
    template: require('../../../templates/activities/message-detail.ejs'),
    className: "message-content-wrapper"
});

// View for filter selection bar
var MessageFilterView = Backbone.Marionette.ItemView.extend({
    template: require('../../../templates/activities/message-filter-bar.ejs'),
    events: {
        'click #search-btn': function() {
            filtermodel.set('search', $('#search-input').val());
            groupcollection.fetchMessages();
        }
    }
});


var filtermodel = new FilterModel();
var groupcollection = new GroupCollection();

// Fetch messages first run
groupcollection.fetchMessages();


// LayoutView to display in center panel of application
module.exports = ViewMessages = Marionette.LayoutView.extend({
    template: require('../../../templates/activities/viewmessages.ejs'),
    className: 'content full-height',
    regions: {
        'messagelistregion': '#messageList',
        'messagedetailregion': '.message-detail',
        'messagefilterregion': '.filter-bar'
    },
    childEvents: { 'showDetail': 'onMessageSelected' },
    onMessageSelected: function (childView, childViewModel) {

        var that = this;

        var detailModel = childViewModel.clone();
        var messageDetailView = new MessageDetailView({model:detailModel});
        that.messagedetailregion.show(messageDetailView);
    },
    onShow: function(){

        var that = this;
        var messagesview = new MessagesView({
            collection: groupcollection
        });

        var messageFilterView = new MessageFilterView();
        that.messagelistregion.show(messagesview);
        $("#messageList").ioslist();

        that.messagefilterregion.show(messageFilterView);
        this.messagedetailregion.on('show', function() {
            console.log('message detail region shown:' + that.messagedetailregion.currentView);
        })
    }
});

我认为这是因为在触发重置事件和刷新视图之前,在成功回调中构建消息分组的工作没有完成。如何让 MessagesView 在后续提取后更新?

更新: 我将 collection 分组到其分层 tree/leaf 结构中的 post-success 逻辑移动到顶层 collection 视图 (MessagesView) 中的自定义事件 (fetchSuccess) :

var MessagesView = Backbone.Marionette.CollectionView.extend({
    childView: MessageGroup,
    initialize: function() {
        this.collection.on('fetch:success', this.fetchSuccess, this);
    },
    fetchSuccess: function() {
        var messagecollection = new MessageCollection();

        groupcollection.each(function(group) {
            var list = group.get('list');

            messagecollection.reset(list);
            group.set('list', messagecollection);
        });
    }
});

在fetch成功回调中触发。我很确定这是呈现 collection 的好方法,但我似乎无法解决 Marionette:

中的错误
**Uncaught TypeError: listening.obj.off is not a function**

有人知道为什么这个 collection 视图不会 re-render??

我能够确定集合中模型的创建发生在重置事件之后,但在构建嵌套模型结构之前:

success: function() {

    var messagecollection = new MessageCollection();

    // Loop through each grouping and set sub-collections
    groupcollection.each(function(group) {
        var list = group.get('list');

        messagecollection.reset(list);
        group.set('list', messagecollection);
    });
};

在任何过滤事件、分组、排序等之后,每次都需要将集合结构修改为这个嵌套层次结构。视图在构建结构之前拾取重置事件,因此子视图没有数据可呈现。我通过在更改后克隆原始集合并让视图呈现克隆的集合来修复此问题:

groupcollection.fetch({
    reset: true,
    data: filtermodel.toJSON(),
    success: function() {

        groupcollection.each(function(group) {
            var list = group.get('list');

            var messagecollection = new MessageCollection(list);
            group.set('list', messagecollection);
        });

        filteredcollection.reset(groupcollection.toJSON());
    }
});