2012-03-01 52 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); 

}