我总是销毁并创建视图,因为随着我的单页应用程序变得越来越大,将未使用的实时视图保留在内存中以便我可以重新使用它们将变得难以维护。
这是我用来清理视图以避免内存泄漏的技术的简化版本。
我首先创建一个 BaseView,我的所有视图都继承自它。基本思想是,我的视图将保留对其订阅的所有事件的引用,以便在处置视图时,所有这些绑定都将自动解除绑定。这是我的 BaseView 的示例实现:
var BaseView = function (options) {
this.bindings = [];
Backbone.View.apply(this, [options]);
};
_.extend(BaseView.prototype, Backbone.View.prototype, {
bindTo: function (model, ev, callback) {
model.bind(ev, callback, this);
this.bindings.push({ model: model, ev: ev, callback: callback });
},
unbindFromAll: function () {
_.each(this.bindings, function (binding) {
binding.model.unbind(binding.ev, binding.callback);
});
this.bindings = [];
},
dispose: function () {
this.unbindFromAll(); // Will unbind all events this view has bound to
this.unbind(); // This will unbind all listeners to events from
// this view. This is probably not necessary
// because this view will be garbage collected.
this.remove(); // Uses the default Backbone.View.remove() method which
// removes this.el from the DOM and removes DOM events.
}
});
BaseView.extend = Backbone.View.extend;
每当视图需要绑定到模型或集合上的事件时,我都会使用 bindTo 方法。例如:
var SampleView = BaseView.extend({
initialize: function(){
this.bindTo(this.model, 'change', this.render);
this.bindTo(this.collection, 'reset', this.doSomething);
}
});
每当我删除视图时,我只需调用 dispose 方法即可自动清理所有内容:
var sampleView = new SampleView({model: some_model, collection: some_collection});
sampleView.dispose();
我与正在编写“Backbone.js on Rails”电子书的人们分享了这项技术,我相信这是他们在本书中采用的技术。
更新:2014-03-24
从 Backone 0.9.9 开始,使用上面所示的相同的 bindTo 和 unbindFromAll 技术将listenTo 和 stopListening 添加到事件中。另外,View.remove会自动调用stopListening,因此绑定和取消绑定就像现在这样简单:
var SampleView = BaseView.extend({
initialize: function(){
this.listenTo(this.model, 'change', this.render);
}
});
var sampleView = new SampleView({model: some_model});
sampleView.remove();