useapply属性

在页面中嵌入代码不当会增加维护的难度,有两种途径可以从视图中分离出代码。

一种途径是你可以监听所关心的事件,然后调用合适的方法进行处理。例如,可以调用onCreate [10], onOK [11], onCancel [12] 事件来完成初始化(initialize),处理(process)和取消(cancel)等工作。

<window id="main" onCreate="MyManager.init(main)"
   onOK="MyManager.process(main)" onCancel="MyManager.cancel(main)"/>

另外,必须有一个名称为MyManager的Java类,内容像下面一样:

import org.zkoss.zul.Window;

public class MyManager {
   public static void init(Window main) { //does initialization
   }
   public static void save(Window main) { //saves the result
   }
   public static void cancel(Window main) { //cancel any changes
   }
}

但是,上面的方法需要你在ZUML页面内嵌入一些代码。在用户界面(UI)内嵌入代码的优点是可以很容易的动态改变行为(特别是在原型阶段),但是这仍然会展现一些维护代码且性能会有一些降低 [13]

use属性

若不想在ZUML页面内使用Java代码,你可以继承一个组件的实现来处理事件,如下。

import org.zkoss.zul.Window;

public class MyWindow extends Window {
   public void onCreate() { //does initialization
   }
   public void onOK() { //save the result
   }
   public void onCancel() { //cancel any changes
   }
}

然后,使用use属性指定类,如下。

<window use="MyWindow">
   ...
</window>

apply 属性

若你喜欢使用MVC(模型-试图-控制者)方法,例如,你不想在window(视图)内嵌入处理代码,可以实现一个类来初始化window。这个类必须实现org.zkoss.zk.ui.util.Composer接口。

import org.zkoss.zk.ui.util.Composer;
import org.zkoss.zul.Window;
public class MyComposer implements Composer {
   public void doAfterCompose(Component comp) {
      ((Window)comp).setTitle("My Title"); //do whatever initialization you want
         //comp is Window since we will specify it to a window later
   }
}

在这里我们假设你有三个监听器, MyCreate,MyOK,和 MyCancel。参考下面的事件章节获取事件监听器的解释。

然后,使用apply属性指定类,如下。

<window apply="MyComposer">
...
</window>

window仍然作为org.zkoss.zul.Window 的一个实例被创建,且作为comp参数被传递给doAfterCompose方法。然后,你可以处理你所希望的初始化。

若你想apply多个composer,使用逗号隔开。另外,你可以使用EL表达式来返回类,它的名称,Composer实例,或Composer实例的集合。

<window apply="MyComposer, AnotherComposer">
   <textbox apply="${c:mycomposer()}"/>
</window>

forward属性一起使用

window通常由一些按钮,菜单项目和其他组件组成。例如,

<window use="MyWindow">
   ...
   <button label="OK"/>
   <button label="Cancel"/>
</window>

当用户点击按钮时,onClick事件会被送至按钮本身。但是这些事件最好在window内处理而不是散落这些按钮。为了这样,你可以按如下方式使用forward属性。

<window use="MyWindow">
   ...
   <button label="OK" forward="onOK"/>
   <button label="Cancel" forward="onCancel"/>
</window>

在这里OK按钮的forward属性指定接收onClick事件后将其作为onOK 事件转向空间所有者(例如,window)。同样,针对Cancel 按钮的onClick事件会转向onCancel事件。因此你可以在MyWindow 命名空间内处理onOKonCancel事件,如下。

public class MyWindow extends Window {
   public void onOK() {
      //called when the OK button is clicked (or the ENTER button is pressed)
   }
   public void onCancel() {
      //called when the Cancel button is clicked (or the ESC button is pressed)
   }
}

除了将onClick事件forward至空间所有者,你可以使用forward属性将任何事件forward至任何组件。参考ZK用户界面标记语言一章中forward属性一节。

zscript实现Java类

zscript中继承Java类,多亏了BeanShell[14]的强大功能,Java类的继承可以按如下的方式完成:

<zscript>
   public class MyWindow extends Window {
   }
</zscript>
<window use="MyWindow"/>

[提示]:很多脚本语言,例如JRuby,也允许开发人员定义可以被Java虚拟机(JVM)存取的类,请参考相应的手册来了解详情。

为了从视图中分离代码,你可以把所有的zscript代码放到单独的文件中,称为mywnd.zs,然后:

<zscript src="/zs/mywnd.zs"/>
<window use="MyWindow"/>

[提示]:你也可以使用初始化指令(initdirective)来指定zscript文件的位置。不同的是初始化指令在所有组件被创建前被赋指(页面初始阶段)。如需更多信息请参考ZK用户界面标记语言一章中init指令一节。



[10] 当ZUML中window产生时onCreate事件会被送出。

[11] 使用者按下ENTER key时onOK事件被送出。

[12] 使用者按下ESC key时onCancel事件被送出。

[13] Java解释器会在运行时解释ZUML页面内指定的代码。

[14] http://www.beanshell.org