我有一个过滤器在处理我的 Backbone 集合。在搜索框中键入搜索并列出实时过滤器。效果很好,或者我是这么想的。当我查看 chrome 中的内存堆快照时,我可以看到每次搜索都会泄漏内存...6 兆 8 兆...不久之后堆快照就会超过 100 兆。
我已经在下面的 View 中隔离了问题。如果我在初始化函数中注释掉 this.listenTo,我似乎不再泄漏内存。
所以我的问题是如何在不泄漏的情况下保持这些事件监听器和集合上的实时过滤。
var View = Backbone.View.extend({
tagName: 'tr',
initialize: function() {
this.listenTo(this.model, 'change', this.render);
this.listenTo(this.model, 'destroy', this.remove);
},
events: {
'click .edit': 'edit',
'click .delete': 'delete',
},
edit: function() { /* EDIT */ },
delete: function() {
this.model.destroy(); //backbone
},
render: function () {
var template = _.template( ProductTemplate )
this.$el.html( template({ this.model.toJSON() }) )
return this;
}
})
var ListView = Backbone.View.extend({
initialize: function()
{
this.collection = new Collection( Products ) //products are bootstrapped on load
},
render: function (terms)
{
this.$el.html( ListTemplate );
var filtered = Shop.products.collection.search(terms)
_.each(filtered, this.addOne, this)
//append list to table
$('#products').html( this.el )
return this
},
addOne: function (product)
{
this.$el.find('tbody').append(
new View({ model: product }).render().el
)
return this
},
});
var Collection = Backbone.Collection.extend({
model: Model,
search : function(letters){
//set up a RegEx pattern
var pattern = new RegExp(letters,"gi")
//filter the collection
return this.filter(function(model)
{
if(letters == "") return true //if search string is empty return true
return pattern.test(model.attributes['Product']['name'])
});
}
});
已解决:
这是我的新搜索方法。我不再过滤集合并重新渲染。我只是循环遍历集合,如果模型与搜索匹配,我们会触发“显示”事件,如果它不在搜索中,我们会触发“隐藏”事件。然后我们在 View 中订阅这些事件并采取相应的行动。
集合中的搜索功能: 搜索:函数(查询){
//set up a RegEx pattern
var pattern = new RegExp(query,"gi")
//filter the collection
this.each(function(model){
if ( pattern.test(model.attributes['Product']['name']) ){
model.trigger('show')
}
else{
model.trigger('hide')
}
});
}
新观点: var ProductView = Backbone.View.extend({
tagName: 'tr',
initialize: function() {
this.listenTo(this.model, 'show', this.show);
this.listenTo(this.model, 'hide', this.hide);
},
hide: function()
{
this.$el.addClass('hide')
},
show: function()
{
this.$el.removeClass('hide')
},
render: function ()
{
var template = _.template( ProductTemplate )
this.$el.html( template( {data: this.model.toJSON(), Utils: Shop.utils} ) )
return this;
}
});
最佳答案
为了扩展@mu 已经评论的内容,您并没有删除您创建的 View 。它们不在 DOM 中,但它们仍在内存中徘徊,因为它们引用了您的模型(因此,垃圾收集器不会为您删除它们)。
你有几个选择:
- 跟踪
addOne
实例化的所有 View ,并在每次调用render
时删除它们。 - 每次更改过滤条件时,让您的代码显示/隐藏 View 而不是实例化/销毁 View 。这是更多的工作,但肯定是更优的解决方案。
关于javascript - 过滤 Backbone 集合时内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14421086/