在 体 模 视图 上 触发 的 Backbone.js 事件

suzh9iv8  于 2022-11-10  发布在  其他
关注(0)|答案(1)|浏览(161)

方案

我继承了旧的 Backbone.js 应用程序与主详细信息的场景。在主视图上,我有项目列表(项目),当我点击一个项目,我可以编辑它的详细信息视图(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');
    },

});

你有什么提示什么可能导致内存泄漏?

tp5buhyn

tp5buhyn1#

看起来所有视图都附加到$content。每当您为此元素创建新视图时,都会有一组新的事件侦听器附加到此元素。
理想情况下,您应该在创建新视图之前删除现有视图,以使用视图的remove方法释放内存。
如果由于某种原因而无法执行此操作,并且希望同时在内存中保留所有创建的视图对象,则它们需要有自己的元素来绑定事件。
您可以通过删除el: $content,来实现这一点。这让我们为每个视图创建一个元素。
然后在创建视图后执行$content.append(view.el)。在创建新视图时,您必须将这些元素从$content中分离出来。

相关问题