2014-01-14 120 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,你是完全正确的。 –

相关问题