$.empty()和Backbone的View.remove()有何区别?

4
我了解当通过 .remove() 移除视图时,Backbone 会在该视图上调用 .stopListening() 方法来移除与该视图相关联的任何事件监听器。这是根据 Backbone 文档所述的: remove view.remove() 从 DOM 中删除视图,并调用 stopListening 来删除视图已经监听的任何绑定事件。 我有一些视图附加到一个只有与它们自身dom操作相关的容器中,这是通过 Backbone 的 events 钩子实现的。
var View = Backbone.View.extend({
   events : {
      'input keyup' : 'searchDropdown'
   },

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

我的问题实际上是在调用$.empty()清空容器并移除其中的视图时是否会泄漏任何内存(无论大小)。如果有,是否有任何良好的约定来访问和调用.remove()删除这些视图?


你需要使用 Backbone Marionette。http://marionettejs.com/ - Michael.Lumley
1个回答

2
您不需要任何特殊的框架来实现这一点,但最好正确地实现删除操作,而不是依赖于浏览器足够聪明以执行此操作。有时在大型应用程序中,您会发现需要专门覆盖删除方法以进行一些特殊的清理 - 例如,您正在使用该视图中的库,该库具有一个“销毁”方法。
现代浏览器往往具有智能的GC,可以处理大多数情况,但我仍然不愿意依赖它。最近我参与了一个Backbone项目,其中没有子视图的概念,通过从“empty”更改为“remove”(在Chrome 43中),我将泄漏节点减少了50%。拥有一个大型的JavaScript应用程序不泄漏内存是非常困难的,我的建议是尽早监控它:如果DOM元素被删除,其监听器也会从内存中删除吗? 注意那些会泄漏大量内存的东西 - 比如图片。我曾经在一个项目上编写过类似以下代码的东西:
var image = new Image();

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

image.src = ...

基本上是预加载程序。而且因为我们没有明确执行image = null,所以GC从未启动,因为回调函数在引用image变量。在一个图片较多的网站上,每次页面转换我们都会泄漏1-2MB,这会导致手机崩溃。在remove覆盖中将变量设置为null可以解决这个问题。
删除子视图只需要像这样做:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接