删除骨干视图后僵尸事件仍然存在

时间:2013-03-01 21:29:39

标签: javascript backbone.js

更新: 根据我的评论,我的问题是我有一个额外的模型,我正在进入视图,我没有解开事件。当我看到事件处理程序被触发时,我假设源是来自this.model而不是this.extra_model,因为我忘记了this.extra_model也被用于错误验证。

解决方案是添加以下内容:

MyView = Backbone.extend({
  //...
  //add method to override BaseView
  cleanUp: function() {
    this.extra_model.off(null, null, this);
    BaseView.prototype.cleanUp.apply(this, arguments);
  },
  //...
});

感谢您查看问题,并对程序员错误感到抱歉。


全部: 在我清理视图后,我遇到了陈旧/僵尸事件仍然受到限制的问题。将自定义事件绑定到模型时会出现问题。当我从dom中删除视图时,我调用'this.model.off(null,null,this);'正如在各种留言板上所建议的那样,但是虽然我可以看到在Chrome调试器工具中删除了“自定义处理程序”回调,但我仍然注意到“自定义处理程序”的事件处理程序被调用的次数超过它应该的次数(每次都有一次额外的)在触发事件时,我在清理后重新创建视图。有人能告诉我清理代码是否丢失了吗?提前谢谢!

BaseView = Backbone.extend({
//...
      displayErrors:function(){},

      cleanUp: function(){
        if (this.model) this.model.off(null, null, this);
        if (this.collection) this.collection.off(null, null, this);
        if (!this.options.persistDataAfterViewCleanup) {
          if (this.model) delete this.model;
          if (this.collection) delete this.collection;
        }
        //_.each(this.subViews, function(view){view.cleanUp();}); not needed yet.
        this.undelegateEvents();
        $(this.el).removeData().unbind();
        //Remove view from DOM
        this.$el.html('');
        this.remove();
      }
});

MyView = BaseView.extend({
  initialize: function(){
    //called manually from model using trigger
    this.model.on('custom-handler', this.displayErrors, this);
  }
});

1 个答案:

答案 0 :(得分:5)

假设您使用的是最新版本的Backbone(0.9.10),则应使用新的Backbone.Events.listenTo方法绑定事件侦听器。使用此方法Backbone将保留对该对象的引用,并在view.remove()上自动清除所有事件绑定:

this.listenTo(this.model, 'custom-handler', this.displayErrors);

您在cleanUp方法(deleteundelegateEventsremoveDataunbind$el.html(''))中所做的所有事情都看起来很多像伏都教编程。根本不需要这些步骤。

您的僵尸视图很可能是由于您自己的代码直接或间接地引用了某些视图。引用可以由事件处理程序,绑定函数,导出的闭包或任何数量的东西保存。我建议您尝试分析您的代码,并使用Chrome开发者工具的Heap profiler工具尝试查找保留的对象及其参考者。

查看my answer in this SO question,其中我描述了一种在特定代码路径中查找内存泄漏的简单方法。虽然你的问题不是直接泄漏内存,但它是关于泄漏引用,其保留的堆大小应该可以帮助你找到保留它们的内容。