创建一个元素的流程可以是反复式的。通过为forEach
属性一个对象集合,开发人员可以控制相关元素要被创建多少次。为了描述方便,如果一个元素被forEach
属性赋值就称其为迭代元素(iterative element)。
在下面的例子中,列表项目被创建了三次。每个项目的label分别为"Best", "Better" 和 "God",
<listbox> <listitem label="${each}" forEach="Best, Better, God"/> </listbox>
如果你有一个存放对象集合的变量,则可以直接为forEach属性指定它。例如,假如你有一个grades变量,如下。
grades = new String[] {"Best", "Better", "Good"};
然后可以使用forEach属性来迭代此变量。注意,你必须使用EL表达式来指定这个集合。
<listbox> <listitem label="${each}" forEach="${grades}"/> </listbox>
迭代(iteration)依赖于forEach
属性指定值的类型。
如果是java.util.Collection
,就会迭代集合(collection)的每个元素。
如果是java.util.Map
,就会迭代map中的每个Map.Entry。
如果是java.util.Iterator
,就会迭代迭代器(iterator)中的每个元素。
如果是java.util.Enumeration
,就会迭代enumeration中的每个元素。
如果是Object[],int[],short[],byte[],char[],float[]或double[]
被指定了,就会迭代数组(array)中的每个元素。
如果是null
,什么也不会产生(被忽略)。
如果被指定的不是以上类型,相关元素仅被赋值(evaluated)一次,就好像一个集合只指定了一个单 独的项目。
<listbox> <listitem label="${each}" forEach="grades"/> </listbox>
在迭代中,一个变量被称为each
,通过指定集合的项目被创建并且赋值。在上面的例子中,首次迭代中,each
被赋值为"Best",然后是"Better",最后是"Good"。
注意each
变量在EL表达式和zscript
中都是可访问的。ZK将会保留以前定义的每个变量,并在迭代完每个元素后将其恢复。
forEachStatus
变量是org.zkoss.ui.util.ForEachStatus
的一个实例(instance),用来保存(hold)当前迭代(iteration)的信息。也主要用于取得封闭元素的项目,这些元素已通过forEach属性赋值。
在下面的例子中,我们使用嵌套迭代元素(nested iterative elements)来产生两个listbox。
<hbox> <zscript> classes = new String[] {"College", "Graduate"}; grades = new Object[] { new String[] {"Best", "Better"}, new String[] {"A++", "A+", "A"} }; </zscript> <listbox width="200px" forEach="${classes}"> <listhead> <listheader label="${each}"/> </listhead> <listitem label="${forEachStatus.previous.each}: ${each}" forEach="${grades[forEachStatus.previous.index]}"/> </listbox> </hbox>
注意forEachStatus
变量在EL表达式和zscript
中都是可访问的。
在事件监听器中使用forEach
和forEachStatus
变量有点棘手(tricky),因为它们仅在组件创建阶段(Component Creation Phase)[35]是可用的(available)。因此,下面的例子是不正确的。当onClick监听器被调用时,each
变量就不可用了。
<window title="Countries" border="normal" width="100%"> <zscript><![CDATA[ String[] countries = { "China", "France", "Germany", "United Kindom", "United States"}; ]]></zscript> <hbox> <button label="${each}" forEach="${countries}" onClick="alert(each)"/> <!-- incorrect!! --> </hbox> </window>
注意按钮(button)标签(label)的赋值方式是错误的,因为它们在同一阶段-----组件创建阶段(Component Creation Phase)。
同时也要注意不能在事件监听器中使用EL表达式。例如,下列代码会执行失败,因为onClick
的监听器并不是Java代码(也就是说,EL表达式在zscript
中是被忽略的)。
<button label="${each}" forEach="${countries}" onClick="alert(${each})"/> <!-- incorrect!! -->
解决方法是我们必须在某处存储each
(和forEachStatus
)的内容,这样当监听器执行时其内容仍是可用的。你可以将其内容存储在任何地方,但是有一个简单的方法来处理,如下:
<window title="Countries" border="normal" width="100%"> <zscript><![CDATA[ String[] countries = { "China", "France", "Germany", "United Kindom", "United States"}; ]]></zscript> <hbox> <button label="${each}" forEach="${countries}" onClick="alert(self.getAttribute("country"))"> <custom-attributes country="${each}"/> </button> </hbox> </window>
就像按钮(button)标签(label),定制属性(custom attributes)的属性在组件创建阶段 (Component Creation Phase)被赋值(evaluated),所以在这里你可以使用each。然后,它被存储在一个定制属性,这个定制属性会在组间存在的期间一直有效(直到组件被移除)。