myView = Backbone.View.extend({
//event binding etc etc
render: function() {
//render some DOM
}
})
anotherView = Backbone.View.extend({
events: {
'click .selector doThis'
},
createNewView: function() {
var view = new myView();
}
})
createNewView
可能会被多次调用。我的理解是,JavaScript的内置垃圾收集不一定会删除变量view
,因为它引用了createNewView
函数完成时仍然存在的对象/代码。
这是对的吗?怎么处理这个?
我目前的方法是在我的应用级别初始化myView
:
myApp.view = new myView()
然后在createNewView
我只是在这上面调用渲染:
myApp.view.render()
基本上,我只有一个,我重新使用它。
另一种方法是跟踪数组中子视图的创建,然后当我知道不再需要它们时,我依次在每个视图上调用.remove()
。
我是在正确的轨道上吗?
我发现第二种方法更好,因为如果myView
在listenTo
的其他对象上创建绑定回调,则只需重新分配变量就不会删除这些回调。也就是说,如果我正在调用new
来实例化视图的新实例,我应该首先在被丢弃的实例上调用remove()
......似乎。
答案 0 :(得分:4)
在您的示例中,您没有将视图的el
放入DOM ,因此没有任何内容引用该视图,然后它将被垃圾收集器收集。
确保视图不再受某种限制的一件好事是在其上调用.remove()
。它将删除:
el
, Backbone .remove
source:
// Remove this view by taking the element out of the DOM, and removing any // applicable Backbone.Events listeners. remove: function() { this._removeElement(); this.stopListening(); return this; }, // Remove this view's element from the document and all event listeners // attached to it. Exposed for subclasses using an alternative DOM // manipulation API. _removeElement: function() { this.$el.remove(); },
正如mu is too short in the comments(以及我几乎所有其他答案中所提到的)所提到的,您应始终favor listenTo
over on
or bind
以避免内存泄漏并轻松解除绑定事件。
渲染子视图时,嵌套在父视图中,一个好的做法是保留子视图的数组,以便稍后在每个视图上调用.remove()
。
简单的列表视图可能如下所示:
var ListView = Backbone.View.extend({
initialize: function() {
// Make an array available to keep all the child views
this.childViews = [];
},
addOne: function(model) {
var view = new Backbone.View({ model: model });
// as you create new views, keep a reference into the array.
this.childViews.push(view);
this.$el.append(view.render().el);
},
renderList: function() {
// replace the view content completely with the template
this.$el.html(this.templates());
// then cleanup
this.cleanup();
// then render child views
this.collection.each(this.addOne, this);
return this;
},
cleanup: function() {
// quick way to call remove on all views of an array
_.invoke(this.childViews, 'remove');
// empty the array
this.childViews = [];
},
});
虽然如果其他对象正在收听它,它将不会被收集并且可能是泄漏。跟踪引用并在不再需要时删除它们非常重要。