0

我需要遍历一组子视图(它们是 UI 小部件)并告诉他们将自己从应用程序中删除。我已确保集合中存在所有 childViews,但是此代码一次只会在一些 childViews/widgets 上调用 removeIfSelected():

 widgets = container.get('childViews')
 widget.removeIfSelected() for widget in widgets

例如,如果有 3 个小部件,则第一次运行时(通过删除按钮)会删除 2 个小部件。我必须再次单击该按钮才能删除最后一个小部件。

如果有 2 个,它将删除一个小部件。如果有 4 个或更多,除了 2 个小部件之外的所有小部件都将被删除,我必须再单击 2 次才能删除最后两个小部件。

我最初的解决方案是运行循环 3 次,以确保删除所有小部件,但这没有通过代码审查,我必须找到一个真正的解决方案。我不确定这是咖啡脚本问题还是 Ember.js 问题。如何确保循环完全执行?

4

1 回答 1

2

听起来像是widget.removeIfSelected()在改变widgets你背后的数组,所以一旦删除一些东西,你的for循环中的长度和索引就会全部搞砸。考虑这个循环:

a = [ 0, 1, 2, 3, 4, 5 ]
for e, i in a
    console.log(i) if(i % 2 == 0)

这显然会0, 2, 4在控制台中产生。然而,这:

a = [ 0, 1, 2, 3, 4, 5 ]
for e, i in a
    a.splice(i, 1) if(i % 2 == 0)
console.log(a)

让你留[1, 2, 4, 5]在里面,a因为a它在被循环时正在被修改。

有两种常见的解决方案:

  1. 向后迭代,以便更改不会影响即将发生的任何事情,它们只会影响您已经经历过的事情。
  2. 制作您正在迭代的内容的副本,以便您迭代一件事并更改其他内容。

第一个看起来像这样:

for i in [widgets.length - 1 .. 0] by -1
    widget.removeIfSelected()

第二个看起来像这样:

widgets = clone(container.get('childViews'))
widget.removeIfSelected() for widget in widgets

您可以在哪里clone制作(浅)数组副本。如果你有下划线,那么你可以使用_.clone

widgets = _(container.get('childViews')).clone()

您也可以手动完成:

clone = (a) -> e for e in a
于 2013-01-02T18:45:21.987 回答