方案
我继承了旧的 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');
},
});
你有什么提示什么可能导致内存泄漏?
1条答案
按热度按时间tp5buhyn1#
看起来所有视图都附加到
$content
。每当您为此元素创建新视图时,都会有一组新的事件侦听器附加到此元素。理想情况下,您应该在创建新视图之前删除现有视图,以使用视图的
remove
方法释放内存。如果由于某种原因而无法执行此操作,并且希望同时在内存中保留所有创建的视图对象,则它们需要有自己的元素来绑定事件。
您可以通过删除
el: $content,
来实现这一点。这让我们为每个视图创建一个元素。然后在创建视图后执行
$content.append(view.el)
。在创建新视图时,您必须将这些元素从$content
中分离出来。