在Backbone.js或Marionette.js中反复创建和销毁视图,而不会造成“内存泄漏”

我怀疑我在backbone.js中处理视图的方式存在缺陷,导致它产生“内存泄漏”.

有一个视图不断被另一个副本覆盖.新副本链接到不同的模型.

我正在创建并在创建子视图时通过设置el选项将视图添加到其父视图中.

发生的奇怪事情是,即使在旧视图的顶部渲染新视图,当我单击“按钮”时,会弹出每个渲染的每个childView的警报,即使他们正在侦听的按钮应该不见了,他们回应新按钮.

我通过调用旧视图上的函数来实现快速修复,以便在添加新视图之前停止侦听事件.但是存在这个问题告诉我,如果用户不经常刷新页面,所有旧视图都会闲置,并且会随着时间的推移而减慢应用程序的速度.

var parent = new (Backbone.Marionette.ItemView.extend({
     ui:{
          child_container: '#child-container'
     },
     onRender: function(){
          // Listen to outside event
          ...
     }
     on_Outside_Event: function(new_model){
          // Quick fix prevents multiple alerts popping up for every child view when "button" is pressed
          this.child_view.destroy_view(); 

          // New child view is created and rendered on top of the one that was there before
          this.child_view = childView({
               el:    this.ui.child_container,  // <-- Is this the problem?
               model: new_model
          })
          this.child_view.render();
     }
}))();

var childView = Backbone.Marionette.ItemView.extend({
     events:{
          'click button': 'on_click_button'
     },
     on_click_button: function(){

          // Alert pops up once for every view that was ever displayed.
          alert('Button clicked');  
     },
     // QUICK FIX
     destroy_view: function(){
          this.undelegateEvents();
     }

}) 

如果这有用,这里是实际应用程序的屏幕截图.约会日历在右边.问题子视图 – 用户想要查看的单个约会视图位于左侧.

当我单击“取消约会”按钮时,即使我正在使用以下事件监听事件,也会为该区域中显示的每个约会调用该函数:事件:{‘click#cancelout-button’:’on_button_click’}

没有其他按钮,交互和其他控件都有同样的问题,我假设因为所有其他实际上实时视图是子约会视图的子视图而不是在子约会视图本身

《在Backbone.js或Marionette.js中反复创建和销毁视图,而不会造成“内存泄漏”》

可能的解决办法?

做了一点搜索,这个修复看起来足够吗?

通常,我认为removeData().unbind();和remove()函数直接在这个.$el上调用,但这在这里不起作用,我想因为我在创建时使用el选项添加了子视图(el:this.ui.child_container)

var childView = Backbone.Marionette.ItemView.extend({
     ...
     // REAL FIX
     destroy_view: function(){
          this.undelegateEvents();

          this.$el.children().removeData().unbind();
          this.$el.children().remove();
     }

最佳答案 我认为你应该让你的父视图成为一个LayoutView(它只是一个具有处理区域iirc的附加功能的ItemView),为你希望这个子视图出现的位置定义一个区域,然后执行:

  Parent = Backbone.Marionette.LayoutView.extend
    regions:
      child: "#child-container"

    on_Outside_Event: ->
      childView = new ChildView(...)
      @getRegion("child").show(childView)

(抱歉,我使用了coffeescript,写的速度更快,但你可以轻松翻译).

Marionette将处理所有事情:关闭您的旧孩子观点,解除绑定事件等.

点赞