$.empty()与 Backbone 网的View.remove()的比较?

klr1opcd  于 2022-11-10  发布在  其他
关注(0)|答案(1)|浏览(135)

我知道当通过.remove()删除视图时,会在该视图上调用.stopListening(),以删除Backbone中与该视图关联的任何事件侦听器。

删除**视图.remove()

  • 从DOM移除检视,并呼叫stopListening来移除检视已监听的任何系结事件**。*

我有一些视图被附加到一个容器中,这些容器通过Backbone的events钩子只包含与dom操作相关的事件。

var View = Backbone.View.extend({
   events : {
      'input keyup' : 'searchDropdown'
   },

   searchDropdown: function () {
      $('dropdown').empty();
      //Appends views based on search
   }
});

我的问题实际上是,当我在一个容器上调用$.empty()时,是否会泄漏任何内存(重要的或不重要的),而这个容器实际上删除了附加在其中的视图。如果是的话,有没有什么好的约定来访问和调用这些视图上的.remove()?

ryoqjall

ryoqjall1#

你不需要任何特殊的框架来完成这个任务,但是正确地执行删除是一个好主意,而不是依赖于足够智能的浏览器来完成这个任务。有时候在一个大的应用中,你会发现你特别需要覆盖remove方法来做一些特殊的清理--比如你在那个视图中使用了一个库,它有一个destroy方法。
一个现代的浏览器倾向于有一个GC,它对于大多数情况来说已经足够智能了,但是我仍然不喜欢依赖它。最近我在Backbone中做了一个项目,它没有子视图的概念,我通过将empty更改为remove,将泄漏节点减少了50(在Chrome 43中)。要让一个大型javascript应用程序不泄漏内存是非常困难的,我的建议是尽早监控它:If a DOM Element is removed, are its listeners also removed from memory?
注意那些会泄漏大量内存的东西--比如图像。我在一个项目中有一些代码,它做了这样的事情:

var image = new Image();

image.onLoad(.. reference `image` ..)

image.src = ...

基本上是一个预加载器。而且因为我们没有显式地执行image = null,所以GC从来没有启动,因为回调引用了image变量。在一个图片较多的网站上,我们在每次页面转换时都会泄漏1- 2 mb,这会导致手机崩溃。在remove覆盖中将变量设置为null修复了这个问题。
在子视图上调用remove就像这样简单:

remove: function() {
    this.removeSubviews();
    Backbone.View.prototype.remove.call(this);
},

removeSubviews: function() {
    if (!_.isEmpty(this.subViews)) {
         _.invoke(this.subViews, 'remove');
         this.subViews = []; 
    }
}

你只需要把你的子视图示例添加到一个数组中。例如,当你创建一个子视图时,你可以有一个像parentView: this这样的选项,并把它添加到父视图的数组中。我以前做过更复杂的子视图系统,但那会工作得很好。在初始化视图时,你可以做如下操作:

var parentView = this.options.parentView;
if (parentView) {
    (parentView.subViews = parentView.subViews || []).push(this);
}

相关问题