4

更新:根据我的评论,我的问题是我有一个额外的模型,我正在传递给我没有解除绑定事件的视图。当我看到事件处理程序被触发时,我假设源来自 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 调试器工具中删除了“custom-handler”回调,但我仍然注意到“custom-handler”的事件处理程序被调用的次数超过了它应该调用的次数(每个额外一个触发事件时,我清理它后重新创建视图的时间)。有人能告诉我我的清理代码是否遗漏了什么吗?提前致谢!

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);
  }
});
4

1 回答 1

5

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

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

您在cleanUp方法中所做的所有事情(delete, undelegateEvents, removeData, unbind, $el.html(''))看起来很像巫毒编程。根本不需要这些步骤。

您的僵尸视图很可能是由于直接或间接地引用了您自己的代码所持有的视图。引用可以由事件处理程序、绑定函数、导出的闭包或任何数量的事物持有。我建议您尝试分析您的代码,并使用 Chrome 开发人员工具的堆分析器工具来尝试查找保留的对象及其引用。

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

于 2013-03-02T09:35:06.197 回答