Backbone事件触发幻像视图

时间:2018-04-06 12:46:50

标签: javascript backbone.js backbone-events

方案

我继承了具有主要细节方案的旧骨干应用程序。在主视图上我有项目列表(项目),当我点击一个项目时,我可以在详细信息视图(ProjectFormView)上编辑它。

问题

当我在ProjectFormView上编辑项目时,所有以前打开的项目都会使用相同的值进行编辑。

详细说明:

我发现,输入更改等UI事件也会在之前打开的ProjectFormViews上触发,因此它看起来像某种内存泄漏。

这是视图的实例化方式:

displayProject: function(appType, appId, projectId) {
    if (this.applicationDetailsModel === undefined || 
        this.applicationDetailsModel.get('formType') !== appType || 
        this.applicationDetailsModel.get('id') !== appId)
    {
        this.navigateTo = 'projects';
        this.navigateToItem = projectId;
        this.navigate('form/' + appType + '/' + appId, { trigger: true });
        return;
    }
    var that = this;
    require(['views/projectFormView'], function(ProjectFormView) {
        var tooltips = that.tooltipsCollection
            .findWhere({ form: 'project' })
            .get('fields');
        if (that.isCurrentView(that.projectFormView, appId, appType) === false) {
            that.projectFormView = new ProjectFormView({
                el: $content,
                tooltips: tooltips,
                projectScale: that.projectScale,
                workTypes: that.workTypes
            });
        }
        that.projectFormView.listenToOnce(that.projectScale, 'sync', that.projectFormView.render);
        that.projectFormView.listenToOnce(that.workTypes, 'sync', that.projectFormView.render);
        that.renderItem(that.projectFormView, that.projectsCollection, projectId, 'projects');
        that.highlightItem('projects');
    });
},

和观点。注意SetValue中的注释

return ApplicantFormView.extend({
    events: {
        'change #newProject input': 'processProject',
        'change #newProject select': 'processProject',
        'change #newProject textarea': 'processProject',
    },

    template: JST['app/scripts/templates/projectForm.hbs'],
    initialize: function (options) {
        this.projectScale = options.projectScale;
        this.workTypes = options.workTypes;
        this.tooltips = options.tooltips;
    },
    render: function () {
        Backbone.Validation.bind(this, {
            selector: 'id'
        });
        this.$el.html(this.template(
            {
                project: this.model.attributes,
                projectScale: this.projectScale.toJSON(),
                workTypes: this.workTypes.toJSON(),
                appType: profileModel.get('loadedAppType'),
                appId: profileModel.get('applicationId')
            }
        ));

        this.$('.datepicker').datepicker({
            endDate: 'today',
            minViewMode: 1,
            todayBtn: 'linked',
            orientation: 'top auto',
            calendarWeeks: true,
            toggleActive: true,
            format: 'MM yyyy',
            autoclose: true
        });
        this.$('.datepicker').parent().removeClass('has-error');
        this.$('.error-msg').hide();
        this.$el.updatePolyfill();
        this.revalidation();
        return this;
    },


    processProject: function (event) {
        this.setValue(event);
        this.save();
    },

    setValue: function (event) {
        //This is called on each input change as many times as many projects were previously opened.
        event.preventDefault();
        var $el = $(event.target),
            id,
            value;

        if ($el.attr('type') === 'checkbox') {
            id = $el.attr('id');
            value = $el.is(':checked');
        } else if ($el.attr('type') === 'radio') {
            id = $el.attr('name');
            value = $('input:radio[name ="' + id + '"]:checked').val();
        } else {
            id = $el.attr('id');
            value = $el.val();
        }
        this.model.set(id, value);
        Dispatcher.trigger('upd');
    },

});

您是否有任何可能导致内存泄漏的提示?

1 个答案:

答案 0 :(得分:0)

看起来所有观点都附加到$content。无论何时为此元素创建新视图,都会将一组新的事件侦听器附加到此元素。

理想情况下,您应该在创建新视图之前删除现有视图,以使用视图remove方法释放内存。

如果由于某种原因无法执行此操作并希望同时保留在内存中创建的所有视图对象,则需要使用自己的元素将事件绑定到。

您可以删除el: $content,来执行此操作 这个让我们的主干为每个视图创建一个元素。

然后在创建视图后执行$content.append(view.el)。 在创建新视图时,您必须从$content分离这些元素。