ZK元素

除了被用于创建组件,ZK元素还被用于控制ZUML页面。

zk 元素

<zk>...</zk>

用于聚集(aggregate)其它元素的特殊元素。不同于一个真实的组件(如hboxdiv),它并不是被创建的组件树的一部分。换句话说,它并不代表任何元素。例如:

<window>
   <zk>
      <textbox/>      <textbox/>
   </zk>
</window>

等价于:

<window>
   <textbox/>   <textbox/>
</window>

那么,它是干什么用的呢?

一个页面中的多个根元素

由于XML语法的限制,我们只能指定一个文档根,因此,如果有多个根组件,你必须使用zk作为文档根来组织起这些根组件。

<?page title="Multiple Root"?>
<zk>
   <window title="First">
   ...
   </window>
   <window title="Second" if="${param.secondRequired}">
   ...
   </window>
</zk>

通用的迭代组件

zk元素,像组件一样,支持forEach属性。因此,你可以使用它根据条件产生不同类型的组件。在下面的例子中,我们假定mycols是包含几个成员的对象集合 isUseText() isUseDate() isUseCombo()

<window>
   <zk forEach="${mycols}">
      <textbox if="${each.useText}"/>
      <datebox if="${each.useDate}"/>
      <combobox if="${each.useCombo}"/>
   </zk>
</window>

属性名称

描述

if

[可选][默认: true]

指定条件为这个元素赋值(evaluate).

unless

[可选][默认: false]

指定条件不为这个元素赋值(evaluate).

forEach

[可选][默认: ignored]

指定一个对象集合,这样zk元素可以依靠(against)集合中的每个对象重复被赋值。如果没有指定或为空,此属性被忽略。如果没有集合对象被指定,仅会被赋值一次就好像有一个单元素的集合被指定。

switch

[可选][默认: none]

为相互排斥条件语句(mutually exclusive evaluation)提供了选择(context)。在此属性内指定的值被称为开关条件。

仅允许zk元素作为其子组件。

case

[可选][默认: none]

在开关语句内提供一个可选的方式。

若其值为以斜线开始结束的字符串,则会被认为是一个正则表达式,用以匹配switch条件。

你可以指定复合case,使用逗号分隔。

choose

[可选][默认: none]

为相互排斥条件语句(mutually exclusive evaluation)提供了选择(context)。

仅允许zk元素作为其子组件。

when

[可选][默认: none]

在choose语句内提供了一个可选的方式。

仅当条件匹配时会被执行。

zscript元素

<zscript [language="Java"]> Scripting codes </zscript><zscript src=" uri " [language="Java"]/>

定义脚本代码,如Java代码,当页面被赋值(evaluated)时会解释此代码。默认的语言为Java(见下文)。你可以使用language属性来选择不同的语言。

zscript 元素有如上所示的两种格式。第一种格式是将脚本代码直接嵌入到页面中。第二种格式是指定一个包含脚本代码的文件。

属性名称

描述

src

[可选][默认:none]

指定包含脚本代码文件的URI。若被指定,脚本代码会被加载,就像直接嵌入到文件中一样。

src属性支持浏览器和按照地方(locale dependent)的URI。换言之,你可以指定~ 或 * 来表示不同的上下文路径,浏览器或本地(locale-dependent) 信息。参考国际化一章来获取细节。

注:文件应包含指定语言的源代码,此代码可以被直接解释。编码必须为UTF-8。不要指定类文件(亦称字节码)。

language

[可选][默认:Java或page指令指定的语言][可选值:Java | JavaScript | Ruby | Groovy]

指定编写脚本代码的语言。

deferred

[可选][默认:false]

是否推迟这个元素的赋值,直到第一个同种语言的非推迟zscript代码需要被赋值。参考下面的如何推迟赋值一节。

if

[可选][默认:true]

指定为这个组件赋值的条件

unless

[可选][默认:false]

指定不为这个组件赋值的条件

如何推迟赋值

当要为第一个zscript代码赋值时,ZK会加载解释器。例如,在下面的例子中,当用户点击按钮时Java解释器会被加载。

<button onClick="alert(&quot;Hi&quot;)"/>

另一方面,由于需要在加载页面时为zscript元素赋值,所以当加载下面的ZUML页面时,解释器会被加载。

<window>
   <zscript>
   void add() {
   }
   </zscript>
   <button onClick="add()"/>
</window>

如果你想推迟解释器的加载,可以将deferred设为true。那么,直到用户点击按钮时,解释器才会被加载。

<window>
   <zscript deferred="true">
   void add() {
   }
   </zscript>
   <button onClick="add()"/>
</window>

[注]:在ifunlesssrc属性中指定的EL表达式的赋值也是延迟的。

[注]:如果到解释器时一个组件被从页面移除,zscript代码会被忽略。例如,前面例子中的window不再属于页面,延迟的zscript也不会被解释。

如何选择一种不同的脚本语言

一个页面可以有多种不同的脚本语言。

<button onClick="javascript:do_something_in_js()"/>
<zscript language="groovy">
do_something_in_Groovy();
</zscript>

如果省略脚本语言,则假定为Java。如果你想改变默认的脚本语言,可以按如下方式使用page指令

<?page zscript-language="Groovy"?>

<zscript>
def name = "Hello World!";
</zscript>

如何支持更多的脚本语言

目前,ZK支持Java, JavaScript, Ruby 和 Groovy。但是,它很容易扩展:

  1. 一个实现org.zkoss.zk.scripting.Interpreter接口的类。如果你想直接处理命名空间,可以继承org.zkoss.zk.scripting.util.GenericInterpreter类。或者,如果解释器支持BSF(Bean Scripting Framework,Bean脚本框架),也可以继承 org.zkoss.scripting.bsh.BSFInterpreter类。

  2. WEB-INF/zk.xml或 zk/config.xml文件中声明脚本语言。

<zscript-config>
<language-name>SuperJava</language-name><!-- case insensitive --!>
      <interpreter-class>my.MySuperJavaInterpreter</interpreter-class>
 </zscript-config>

参考the Developer's Reference来获取关于WEB-INF/zk.xml的细节。参考the Component Development Guide来获取关于zk/config.xml的细节。

attribute元素

定义一个闭合元素的XML属性。元素的内容为属性值,而name属性用于指定属性名称。如果属性值比较复杂或属性为条件式的,这比较有用。

<window>
   <attribute name="title" if="${new}">Untitled</attribute>
   <attribute name="title" unless="${new}">${title}</attribute>
</window>

这里olli是本地内容的一部分。它们不是ZK组件。它们最终会被转换为字符串实例,并分配给指定的attribute。如果这个值有三个元素,那么上面的代码等价于:

<html>
   <attribute name="content"><![CDATA[
      <ol>
         <li>${values[0]}</li>
         <li>${values[1]}</li>
         <li>${values[2]}</li>
      </ol>
   ]]></attribute>
</html>

属性名称

描述

name

[必须]

指定属性名称。

trim

[可选][默认:false]

指定是否省略属性值开头及末尾的空格。

if

[可选][默认:none]

指定为这个元素赋值的条件。

unless

[可选][默认:none]

指定不为这个元素赋值的条件。

variables元素

定义一套变量。如果有一个父组件和页面,如果在页面级声明,它等价于ComponentsetVariable方法。

如下所述,variables可以很方便的指定变量而无需编程。

<window>
   <variables rich="simple" simple="intuitive"/>
</window>

等价于:

<window>
   <zscript>
      self.setVariable("rich", "simple", false);
      self.setVariable("simple", "intuitive", false);
   </zscript>
</window>

当然,也可以为值指定EL表达式。

<window>
   <window id="w" title="Test">
      <variables title="${w.title}"/>
      1: ${title}
   </window>
   2: ${title}
</window>

就像ComponentsetVariable方法,你可以按如下方式控制是否为当前的ID空间声明局部变量。如果没有指定,则假定为local=”false”

<variables simple="rich" local="true"/>

composite属性一起使用 List 和 Map值

默认情况下,执行EL表达式之后,值会被直接分配给变量,如果有的话。例如,如果more为"orange","apple, ${more}"会被解释成"apple, orange",并分配给 more变量。

如果你想指定一个list值,则可以使用composite属性,和list一起,如下。

<variables simple="apple, ${more}" composite="list"/>

然后,它会被转换位含有两个元素的list。第一个元素是"apple",第二个元素是"orange"。

如果你想指定一个map值,则可以使用composite属性,和map一起,如下。

<variables simple="juice=apple, flavor=${more}" composite="map"/>

然后,它会被转换为一个含有两个实条目的map。第一个为是("juice", "apple"),第二个是("flavor", "orange")。

null(The null Value)

在下面的例子中,var是一个空字符串。

<variables var=""/>

为了为变量指定一个null值,可以使用下面的语句。

<variables var="${null}"/>

为一个变量分配保留名

为一个变量指定保留名,例如, forEach,你必须指定一个名命空间(除了ZK命名空间可以任选),如下。

<variables m:forEach="a value" xmlns:m="http://whatever.com"/>

然后,forEach会被认为是一个变量,而不是迭代条件。

custom-attributes元素

定义一套定制属性。定制属性为与一个特定范围相关联的对象。可接受的范围包括组件,空间,页面,桌面,会话和应用(component, space, page, desktop, session and application)。

如下所述,custom-attributes属性可以方便的指派定制属性而无需编程。

<window>
   <custom-attributes main.rich="simple" very-simple="intuitive"/>
</window>

等价于:

<window>
   <zscript>
      self.setAttribute("main.rich", "simple");
      self.setAttribute("very-simple", "intuitive");
   </zscript>
</window>

此外,你可以指定定制属性的范围。

<window id="main" title="Welcome">
   <custom-attributes scope="desktop" shared="${main.title}"/>
</window>

等价于:

<window id="main">
   <zscript>
      desktop.setAttribute("shared", main.title);
   </zscript>
</window>

注意EL表达式依靠创建的组件被赋值。有时它是微妙的通知(it is subtle to notice)。例如,在下面的代码中,${componentScope.simple}被赋值为null。为什么呢? 这是<label value=

"${componentScope.simple}"/>的一个快捷方式(shortcut)。换言之,当EL被赋值时,组件,self,是lable而不是window

<window>
   <custom-attributes simple="intuitive"/>
   ${componentScope.simple}
</window>

等价于:

<window>
   <custom-attributes simple="intuitive"/>
   <label value="${componentScope.simple}"/><!-- self is label not window -->
</window>

[提示]:不要混淆<attribute>与<custom-attributes> 。他们毫不相干。 attribute 元素是定义闭合元素属性的一种方式,而custom-attributes 被用于为一个特定范围指派定制属性。

属性名称

描述

scope

[可选][默认:component]

指定定制属性关联的范围。

composite

[可选][默认:none]

指定值的格式。可以为none, list 或 map

参考variables 元素 章节获取更多信息。。

if

[可选][默认:none]

指定为这个元素赋值的条件。

unless

[可选][默认:none]

指定不为这个元素赋值的条件。