2014-01-14 162 views
0

我正在擴展Backbone.View以支持子視圖,我有一個addSubview方法,它只是將一個Backbone視圖添加到一個散列。很簡單。我現在試圖讓它如此,只要你看到它破壞所有的子視圖。我認爲這將是很容易爲好,但我的方法在一個無限循環會:這是爲什麼遞歸併導致無限循環?

destroy: function() { 
    debugger; 
    // Call destroy on all subviews. If the subviews have subviews they'll 
    // be destroyed as well 
    for (var v in this._subviews) { 
    this._subviews[v].destroy(); 
    } 

    // Instead of calling `delete` on every view we wipe everything out after 
    // we're done destroying all the views 
    this._subviews = {}; 

    // Finally, since all the subviews are destroyed it's safe to destroy 
    // this view 
    this.remove(); 
}, 

會發生什麼事是,調試器被稱爲第一次和this是視圖destroy被稱爲(右) ,第二次在第一個子視圖上調用(右側),第三次 - 它仍然繼續調用第一個子視圖。播放通過一步一步的:

  1. 點擊調試
  2. 獲取到this._subviews[v].destroy();線和v == 1子視圖
  3. 跳回到頂部調試器。

就是這樣。它永遠重複。任何想法或建議?

演示:http://jsbin.com/iyApuga/1/edit

+0

你可以創建一個小提琴嗎? – thefourtheye

+0

@thefourtheye在這裏你去:http://jsbin.com/iyApuga/1/edit –

回答

3

這到底是怎麼發生的是,所謂的_subviewsobject被存儲在Foo.View的原型(骨幹extend方法是這樣做的),並因此被Foo.View所有實例共享。在此處,這是設置:

Foo.View = Backbone.View.extend({ 
    _subviews: {}, // right here 

,因爲當你把你的第一個子視圖,它被添加到this._subviews這會導致一個問題。由於_subviews對象正在被View的每個實例共享,因此當您將子視圖添加到子視圖時,所有其他視圖都認爲View是它們自己的子視圖。

具體來說,這裏發生了什麼,就是當你調用.destroy(),在你的循環,在所有子視圖調用destroy()頂部意外呼籲destroy()上完全相同查看一次。該_subviews變量不被清除出去,直到循環後幾行:

// Instead of calling `delete` on every view we wipe everything out after 
// we're done destroying all the views 
this._subviews = {}; 

正因爲如此,它,因爲它是迭代的_subviews同一列表一遍又一遍,陷入放在了第一位變爲無窮大這似乎永遠不會被刪除。

爲了讓世界高興起來,_subviews對象應該是實例變量,而不是View原型。要做到這一點,你應該爲每一個新的View分配一個新的:

initialize: function() { 
    this._subviews = {}; 
    } 
2

問題是_subviews被父Foo孩子Foo實例之間共享。解決方法是初始化_subviews爲每個實例:

initialize: function() { 
    this._subviews = {}; 
} 

它試圖在面向類的風格使用JavaScript的時候是一個很常見的問題。

+0

Awh,你是完全正確的。 –

相關問題