在Flex中,我有一个xml文档,如下所示:
var xml:XML = <root><node>value1</node><node>value2</node><node>value3</node></root>
在运行时,我想为root下的每个节点创建一个TextInput控件,并将值绑定到XML中的值。据我所知,我不能在运行时使用BindingUtils绑定到e4x节点(请告诉我,如果我错在这里!),所以我试图手工完成这个:
for each (var node:XML in xml.node)
{
var textInput:TextInput = new TextInput();
var handler:Function = function(event:Event):void
{
node.setChildren(event.target.text);
};
textInput.text = node.text();
textInput.addEventListener(Event.CHANGE, handler);
this.addChild(pileHeightEditor);
}
我的问题是,当用户编辑其中一个TextInput时,被分配的节点始终是for循环中遇到的最后一个节点。我习惯于使用C#中的这种模式,每次创建一个匿名函数时,都会使用所使用值的值的“快照”,因此每个处理函数中的“node”会有所不同。
如何“处理”要在处理程序中使用的节点的当前值的“快照”?或者我应该在Flex中使用不同的模式吗?
答案 0 :(得分:2)
不幸的是,ActionScript中的函数闭包工作很奇怪/很差。变量只有在超出范围时才会获得“快照”。不幸的是,变量是函数作用域,而不是块作用域。所以它最终不会像你想要的那样工作。
您可以创建一个字典来映射 TextInput - &gt;节点,或者您可以将节点存储在TextInput's
数据属性中。
我希望你所描述的内容能够正常工作,因为它是一种简单/有效的表达方式。
答案 1 :(得分:2)
闭包只捕获变量的引用,而不是当前值。由于局部变量是函数范围的(不是块范围的),因此每次迭代循环都会创建一个闭包,捕获对同一变量的引用。
您可以将TextInput创建代码提取到一个单独的函数中,这将为您提供一个单独的变量实例来捕获闭包。像这样:
for each (var node:XML in xml.node)
{
var textInput:TextInput = createTextInput(node);
this.addChild(pileHeightEditor);
}
...
private function createTextInput(node:XML) : TextInput {
var textInput:TextInput = new TextInput();
var handler:Function = function(event:Event):void
{
node.setChildren(event.target.text);
};
textInput.text = node.text();
textInput.addEventListener(Event.CHANGE, handler);
return textInput;
}