从内存中删除旧模型

时间:2014-11-08 18:04:47

标签: javascript backbone.js

我创建了简单的示例http://jsfiddle.net/n7tntcb5/

$ (function () {
'use strict';

var ButtonView = Backbone.View.extend ({
    tagName : 'button',

    events : {
        'click' : 'onClick'
    },

    initialize : function (options) {
        this.collection = options.collection;
    },

    render : function () {
        this.$el.html ('Click');
        return this;
    },

    onClick : function (event) {
        this.collection.reset ([
            { "id" : _.random (0, 1000), data : new Array (100000).join ('a') },
            { "id" : _.random (0, 1000), data : new Array (100000).join ('a') },
            { "id" : _.random (0, 1000), data : new Array (100000).join ('a') }
        ]);
    }
});

var ListView = Backbone.View.extend ({
    tagName : 'ul',

    initialize : function (options) {
        options || (options = {});

        this.views = [];
        this.collection = options.collection;

        this.listenTo (this.collection, 'reset', this.render);
    },

    empty : function () {
        _.each (this.views, function (view) {
            view.remove ();
        });

        this.$el.empty ();
    },

    render : function () {
        this.empty ();

        this.collection.each (function (model) {
            var view = new ListItemView ({ model : model });
            this.views.push (view);
            this.$el.append (view.render ().el);
        }, this);

        return this;
    }
});

var ListItemView = Backbone.View.extend ({
    tagName : 'li',

    initialize : function (options) {
        options || (options = {});

        this.model = options.model;
        this.collection = options.collection;

        this.listenTo (this.model, 'change', this.render);
    },

    render : function () {
        this.$el.html (this.model.get ('id'));
        return this;
    },

    remove : function () {
        if (this.model) {
            //this.model.clear ();
            delete this.model;
        }
    }
});

var Model = Backbone.Model.extend ({
    defaults : {
        id : null,
        name : '',
        data : ''
    }
});

var Collection = Backbone.Collection.extend ({
    model : Model,

    parse : function (response, options) {
        return response.models || response;
    }
});

var collection = new Collection ();
var list = new ListView ({ collection : collection });
var button = new ButtonView ({ collection : collection });

$ ('body')
    .append (list.render ().el)
    .append (button.render ().el);
});

在“Backbone Eye”Firefox插件或Chrome的“Backbone Debugger”中,我看到每次点击按钮都会不断增加模型数量。如何从旧对象中释放内存?

1 个答案:

答案 0 :(得分:3)

您的empty功能并未清理所有内容。当然,您在remove中的所有内容上调用this.views,但您永远不会清空views数组。试试这个版本:

empty: function() {
    _.each(this.views, function(view) {
        console.log(view.cid)
        view.remove();
    });

    this.$el.empty();
}

并在点击按钮几次时观看控制台:http://jsfiddle.net/ambiguous/27b15fsr/

您的ListView最终会在其ListItemView数组中增加viewsempty: function() { _.each(this.views, function(view) { view.remove(); }); this.$el.empty(); this.views = [ ]; // <------ } 个引用,并且这些僵尸视图将引用该集合,该集合将引用模型。你需要堵塞这个漏洞:

initialize
顺便说一句,您不需要在this.collection = options.collection; 方法中执行此操作:

new View([options])

Backbone将自己处理;来自fine manual

  

构造函数/初始化 model

     

有几个特殊选项,如果通过,将直接附加到视图:collectionelidclassNametagNameattributesevents和{{1}}。