无论我如何删除视图,Backbone都会离开Detached DOM元素

时间:2014-04-16 11:20:31

标签: javascript jquery dom backbone.js

我正在努力通过单页面应用程序获得内存管理的概念。这是我的代码:

var FilterModel = Backbone.Model.extend({});
    var taskView = Backbone.View.extend({
        template: _.template('<h1><%= title %></h1>'),
        initialize: function(){
            this.render();
            this.listenTo(this.model, 'destroy', this.remove);
            console.log(this.model)
        },
        render: function(){

            this.$el.html(this.template(this.model.toJSON()));
            return this;
        },
        events:{
            'click h1': 'removeView'

        },
        removeView: function(){
            this.model.destroy();
            console.log('removed');

        }
    });
    var filterModel = new FilterModel({title: 'Test'});
    var taskview = new taskView({model:filterModel});

// I make heap snapshot before and after the change!
    setTimeout(function(){
        $("h1").click()}, 3000
    )
    $('body').append(taskview.$el);

许多文章都告诉我,使用“删除”和“销毁”会在删除DOM树时清除任何内存泄漏。

但Chrome个人资料实用程序则另有说法。无论我做什么,我都会得到分离的DOM元素。

UPDATE !!! 在回复中尝试了一些内容后,我仍然可以在Google Chrome中使用此功能: 这是jsfiddle:http://jsfiddle.net/HUVHX/ enter image description here

2 个答案:

答案 0 :(得分:1)

所以Janck,你可以在这里找到答案: Backbone remove view and DOM nodes

问题是你必须做的不仅仅是移除模型和视图。

  

当您尝试关闭视图时,您需要正确销毁所有挂起的事件和其他绑定。

我不知道你是否知道 Marionette.js (Backbone.Marionette),但它是Backbone的一个很好的扩展来处理这个 Zombie Views 并创建健壮的JS应用程序。

您也可以阅读一些有关此内容的文章,我们在我发布的Stackoverflow链接中指出了它们。

http://lostechies.com/derickbailey/2011/09/15/zombies-run-managing-page-transitions-in-backbone-apps/

http://lostechies.com/derickbailey/2012/03/19/backbone-js-and-javascript-garbage-collection/

但逻辑是这样的:如果View正在倾听模型,那么相反也会发生,所以您总是会在DOM中获得View的实例

答案 1 :(得分:1)

任务视图仍然强烈引用this.el,虽然它没有连接到dom。这不是内存泄漏,因为任务视图也由它的变量强烈支持

要测试我的假设,只需添加:

removeView: function(){
  this.model.destroy();
  this.el = undefined;
  this.$el = undefined;
}

另一种方法是undef taskview var

修改

当我更改:"click h1" : "removeView""click": "removeView"它解决了分离的dom节点泄漏。

我怀疑这与jquery选择器缓存有关。

您可以在骨干代码中看到,区别在于使用选择器调用jquery on函数:

if (selector === '') {
   this.$el.on(eventName, method);
} else {
  this.$el.on(eventName, selector, method);
}

我试图将缓存深入到jquery代码中,没有运气。