2012-03-01 131 views
19

我有一个顶级的PageView,当路由发生变化时它会重新呈现自己。我有许多嵌入到此PageView中的嵌套子视图。如果我要重新呈现PageView,是否需要将所有嵌套的子视图与PageView一起移除/解除绑定,还是只需要移除/解除绑定PageView?如果我需要删除/取消绑定所有子视图,那么执行此操作的最佳方法是什么?Backbone.js - 删除所有子视图

+0

你是什么意思解除子视图?你的意思是事件吗? – Trevor 2012-03-02 00:19:33

回答

35

是的,你需要正确地删除和解除绑定他们:

http://lostechies.com/derickbailey/2011/09/15/zombies-run-managing-page-transitions-in-backbone-apps/

最简单的方式做,这是存储在父视图的子视图数组。然后,在父视图,遍历数组close方法,并呼吁对孩子意见close方法:

ParentView = Backbone.View.extend({ 
    initialize: function(){ 
    this.childViews = []; 
    }, 

    render: { 
    for (var i = 0; i < 10; i++){ 
     var childView = new ChildView(); 
     // do stuff with the child view 
     this.childViews.push(childView); 
    } 
    }, 

    close: function(){ 
    this.remove(); 
    this.unbind(); 
    // handle other unbinding needs, here 
    _.each(this.childViews, function(childView){ 
     if (childView.close){ 
     childView.close(); 
     } 
    }) 
    } 
}); 

一定要调用close方法父视图,当你准备好了要删除/替换。这将确保所有的孩子都得到适当的清理(假设他们都有自己的close方法)。

+0

嘿德里克,我遵循你的建议,但是在关闭视图+它是子视图时,我经历了很长时间的延迟。在某些情况下,它可能长达5-10秒。看来延迟来自this.remove()。你知道为什么吗? – ragulka 2012-03-26 15:07:29

+0

这是相当长,很糟糕!老实说,我从来没有见过这种情况......你要移除的DOM结构有多大?我唯一的猜测将是一个非常慢的浏览器,和/或一个非常大的DOM节点集。 – 2012-03-26 17:16:57

+0

嘿,没关系 - 它似乎是一个jQuery插件的问题,而不是与视图的remove()函数冲突:http://stackoverflow.com/questions/9877786/calling-jquery-remove-on-custom-ui -widget-causes-infinite-loop/9878287#9878287 – ragulka 2012-03-26 19:29:55

2

而不是保留一个儿童数组视图,可以遍历视图的所有属性,看看哪些是Backbone.View的一个实例;您需要确保在父视图中为每个子视图设置一个属性。

在下面的示例中,子视图设置为父视图的属性。我不确定在所有属性中循环的性能会如何,但是,跟踪子视图的单独数据结构可能更容易。

例子:

var ContextView = Backbone.View.extend({ 
    initialize: function() { 
     // views render themselves via their initialize methods 
     this.titlebar = new TitlebarView({el: $("#titlebar")});  
     this.toolbar = new ToolbarView({el: $("#toolbar")}); 
     this.content = new ContentView({el: $("#content")}); 
    }, 
    removeChildViews: function() {  
     for(var prop in this){ 
      if (this[prop] instanceof Backbone.View) { 
       console.log("This is a view: "+ prop + ' in ' + this[prop]);  
      } 
     } 
    }, 
    render: function() { 
     this.$el.html(this.el); 
    } 
    }); 
3

一个简单的和模块化的类,你可能会发现有用。

ContainerView = Backbone.View.extend({ 
    initialize: function() { 
    this.children = []; 
    }, 
    remove: function() { 
    Backbone.View.prototype.remove.apply(this, arguments); 
    this.removeAllChildren(); 
    }, 
    removeAllChildren: function() { 
    _.each(this.children, function(view) { view.remove(); }); 
    this.children = []; 
    }, 
    appendAllChildren: function() { 
    _.each(this.children, function(view) { this.$el.append(view.render().$el); }, this); 
    } 
}); 

用法:

MyView = ContainerView.extend({ 
    render: function() { 
    this.removeAllChildren(); 
    this.$el.empty(); 

    // For each child view... 
    // this.children.push(new SomeControl(...)); 

    this.appendAllChildren(); 
    return this; 
    } 
}); 
0

有点像Zengineer写的,我喜欢打补丁Backbone.View.remove全球像下面,使附着在这个孩子的任何意见被删除

var originalRemove = Backbone.View.prototype.remove; 

Backbone.View.prototype.remove = function() 
{ 

    for (var view in this){ 
    if (this[view] instanceof Backbone.View && this[view] != this) { 
     this[view].remove(); 
    } 
    } 


    originalRemove.apply(this, arguments); 

}