Javascript 提线木偶CollectionView在collection.fetch之后不重新呈现

Javascript 提线木偶CollectionView在collection.fetch之后不重新呈现,javascript,backbone.js,underscore.js,marionette,frontend,Javascript,Backbone.js,Underscore.js,Marionette,Frontend,我有一个“电子邮件”风格的应用程序,可以显示按日期分组的邮件。当应用程序加载时,将获取一个浅层消息集合,并将其加载到主干集合中。集合中的每个模型表示分组中的消息列表。MessageGroup表示一组消息,而MessagesView显示消息组 这一切都很好,直到再次获取集合,就像应用过滤器后一样,只显示组标题,而不显示其中的消息。我已尝试触发MessagesView可以侦听的事件,然后重新呈现自身,但出现错误:listening.obj.off不是函数 var MessageModel = Bac

我有一个“电子邮件”风格的应用程序,可以显示按日期分组的邮件。当应用程序加载时,将获取一个浅层消息集合,并将其加载到主干集合中。集合中的每个模型表示分组中的消息列表。
MessageGroup
表示一组消息,而
MessagesView
显示消息组

这一切都很好,直到再次获取集合,就像应用过滤器后一样,只显示组标题,而不显示其中的消息。我已尝试触发
MessagesView
可以侦听的事件,然后重新呈现自身,但出现错误:
listening.obj.off不是函数

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);
        })
    }
});
我认为这是因为在触发重置事件和刷新视图之前,在成功回调中构建消息分组的工作没有完成。如何在后续获取后更新
消息视图

更新: 我将成功后将集合分组到其分层树/叶结构的逻辑移动到顶级collectionview(
MessagesView
)中的自定义事件(fetchSuccess):

它在提取的成功回调中被触发。我很确定这是一种很好的呈现收藏的方法,但我似乎无法回避木偶中的错误:

**Uncaught TypeError: listening.obj.off is not a function**

有人知道为什么此collectionview不会重新渲染吗???

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

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());
    }
});
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());
    }
});