过滤主干集合时内存泄漏

时间:2013-01-20 02:19:39

标签: javascript backbone.js backbone-events

我的主干系列上有一个过滤器。在搜索框和列表实时过滤器中键入搜索。工作得很好,或者我认为。当我查看chrome中的内存堆快照时,我可以看到每次搜索时内存泄漏... 6 megs 8 megs ...不久堆快照就是100+ megs。

我已在下面的视图中找出了问题。如果我在初始化函数中注释掉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'])
        });
    }


});

解决:

这是我的新搜索方法。我不再过滤集合和重新渲染。我只是循环遍历集合,如果模型匹配搜索,我们触发'show'事件,如果它不在搜索中,我们触发'hide'事件。然后我们在视图中订阅这些事件并采取相应的行动。

来自集合的搜索功能:     搜索:function(query){

    //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;
    }

});

1 个答案:

答案 0 :(得分:4)

要扩展@mu已经评论过的内容,您不会删除自己创建的视图。它们不在DOM中,但它们仍然在内存中闲置,因为它们具有对模型的引用(因此,垃圾收集器不会为您删除它们)。

您有几个选择:

  1. 跟踪addOne实例化的所有观看次数,并在每次调用render时将其删除。
  2. 使代码显示/隐藏视图,而不是每次更改过滤条件时实例化/销毁。这是更多的工作,但肯定是更优化的解决方案。