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
可能会被调用多次。我的理解是变量 view
不一定会被 JavaScript 的内置垃圾回收删除,因为它引用了 createNewView
时仍然存在的对象/代码。功能完成。
这是正确的吗?怎么处理这个问题?
我当前的方法是初始化myView
一旦达到我的应用程序级别:
myApp.view = new myView()
然后在 createNewView
我只是对此调用渲染:
myApp.view.render()
本质上,我只拥有其中一个,而且我会重复使用它。
另一种方法是跟踪数组中 subview 的创建,然后我调用 .remove()
当我知道不再需要它们时,依次对每一个进行处理。
我走在正确的道路上吗?
我认为第二种方法更好,因为如果 myView
使用 listenTo
在其他对象上创建绑定(bind)回调,这些不会简单地通过重新分配变量来删除。也就是说,如果我打电话 new
要实例化 View 的新实例,我应该调用 remove()
首先是关于被丢弃的实例......看来。
最佳答案
在您的示例中,您没有将 View 的 el
放入 DOM,因此没有任何内容引用该 View ,然后它将被垃圾收集器收集。
确保 View 不再绑定(bind)到某些内容的一件好事是调用 .remove()
就在上面。它将删除:
- 来自 DOM 的 View 的
el
, - jQuery DOM 事件
- Backbone 事件监听器。
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
以避免内存泄漏并简化解除绑定(bind)事件。
渲染嵌套在父 View 中的 subview 时,一个好的做法是保留 subview 的数组,以便稍后对每个 subview 调用.remove()
。
一个简单的 ListView 可能如下所示:
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 = [];
},
});
尽管如果其他对象正在监听它,它不会被收集并且可能是泄漏。跟踪引用并在不再需要时将其全部删除非常重要。
关于javascript - 在 Backbone.js 中实例化 subview 时如何避免内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41595213/