zk页面生命周期
一、组件的生命周期
加 载页面的生命周期:(1)页面初始化阶段-->(2)组件创建阶段-->(3)事件处理阶段-->(4)响应阶段。在阶段1,ZK处理 被称为init的预处理指令,如果没有这样的指令存在,这一阶段将被跳过,注意:当页面初始化阶段执行时页面还没有被放到桌面上。在阶段2,ZK加载器解 释ZUML页面,并创建和初始化组件,注意:开发人员可以通过监听onCreate或者实现org.zkoss.ui.ext.AfterCompose 接口来完成某些特殊的任务。AfterCompose在组件创建阶段被调用,而onCreate是由事件监听器处理的。在阶段3,ZK为桌面上的时间队列 逐个调用监听器,对于每个监听器将会启用一个独立的线程,因此某个监听器被挂起不会影响到其它事件的处理过程。在阶段4,在所有的事件被处理后,zk就会 把这些组件以规则的HTML页面的形式发送到浏览器。为了发送一个组件,组件的redraw(java.io.Writer out)throws java.io.IOException方法会被调用,在这个方法中一个组件的实现(Implementation)不会更改其它组件的内容。
更 新页面的生命周期:Zk AU引擎处理来自客户端的ZK请求分为三个阶段:请求处理阶段、事件处理阶段、响应阶段。在请求处理阶段,依据特定的请求ZK AU引擎有可能更新相关组件的内容,这样它们的内容就和客户端展示的内容相同了,然后ZK AU引擎把响应事件放到一个队列中;事件处理阶段与组件创建阶段中的事件处理是相同的,启动一个独立的线程逐个处理事件;在所有的事件处理完毕后,ZK就 会重绘受影响的组件,生成相应的ZK响应并把这些响应发送到客户端,然后客户端引擎基于收到的响应更新浏览器端的DOM树。究竟是更新组件的整个视图还是 只更新浏览器端中的属性取决于组件的实现,权衡交互性与简单性是组件开发者的责任。
二、组件的垃圾回收机制
一旦一个组件被分离了页面,它就不再被ZK管理了,如果应用程序也不再引用它,这个组件占用的内存会被JVM的垃圾收集器回收。
三、事件监听与处理
关 于延迟监听器:默认情况下,在客户端产生的事件会被立即发送到服务器,但是也有一些事件监听器被用于保存服务器端的状态,而不是为用户提供视图响应,换句 话说,这些监听器监听的事件不需要被立即发送。为了使得一个事件监听器可延迟,需要实现 org.zkoss.zk.ui.event.Deferrable接口。
事 件监听器的调用顺序(以onClick事件为例):1、调用被加入到目标组件上并实现了org.zkoss.zk.ui.event.Express接口 的事件监听器的相应方法,先被加入的先被调用。Express接口是一个标记接口;2、如果需要调用目标组件上onClick属性指定的脚本;3、调用被 加入到目标组件上并且未实现org.zkoss.zk.ui.event.Express接口的事件监听器的相应方法,先被加入的先被调用;4、调用目标 组件上相应的成员方法(在这里是onClick方法);5、调用目标组件所属页面上注册的所有事件监听器的相应方法,先被加入的先被调用。
中断调用序列:可以调用org.zkoss.zk.ui.event.Event的stopPropagation方法中断调用序列,一旦调用了这个方法,随后的事件监听器将会被忽略。
四、线程模型
对于每一个桌面,事件被有序处理,是单线程的;就像开发桌面应用程序一样,开发人员无需考虑多线程的情况,所有要做的事情就是注册事件监听器并处理事件。
五、ZK用户界面标记语言
简介:zk用户界面标记语言(ZUML)是基于XML的,每一个XML元素描述了要创建的组件,一个XML属性描述了将要被创建的组件的初始值,一个XML处理指令描述了如何处理整个页面(如页面的标题),不同组件集通过XML命名空间来区分:(XUL:http://www.zkoss.org/2005/zul XHTML: http://www.w3.org/1999/xhtml)
可以用CDATA段来使XML解释器不要解释其中的文本,例如:<zscript><![CDATA[……]]></zscript>
XML注释:<!--注释内容-->
指定字符编码: <?xml version="1.0" encoding="UTF-8" ……?>(必须放在文件的第一行)
命名空间:xmlns="……" 指定一个命名空间,并用它作为默认的命名空间;xmlns:xx="……" 指定一个命名空间,并使用xx来呈现这个命名空间。
六、ZK隐含对象
对象名称 | 描述 |
self | org.zkoss.zk.ui.Component组件本身 |
spaceOwner | org.zkoss.zk.ui.IdSpace 组件的空间所有者 与self.spaceOwner相同 |
page | org.zkoss.zk.ui.Page 页面 与self.page相同 |
desktop | org.zkoss.zk.ui.Desktop 桌面 与self.desktop相同 |
session | org.zkoss.zk.ui.Session 会话 |
application | org.zkoss.zk.ui.WebApp Web应用程序 |
applicationScope | java.util.Map 与org.zkoss.zk.ui.WebApp中的getAttributes()相同 |
requestScope | java.util.Map 与org.zkoss.zk.ui.Execution中的getAttributes()相同 |
event | org.zkoss.zk.ui.event.Event或派生类 事件 仅在事件监听器中可用 |
七、进程指令
Page指令:描述了页面的属性
Component 指令:为某页面定义新的组件,使用此指令定义的组件仅对该指令所在的页面有效。为了定义所有页面中均可见的组件,可以使用附加语言插件(language addon)即一个XML文件,用来定义在web应用程序中所有页面都可以使用的组件,有两种方式:一种是宏,另一种是类。
init指令,有两种格式:一、指定一个类用来处理具体应用(application-specific)的初始化;二、指定一个zscript文件用于处理具体应用的初始化。
variable- resolver指令:为zscript解释器指定一个变量分解器(实现VariableResolver接口)用来分解未知变量,下面是zk结合 spring的例子,它分解了在spring框架中声明的Java Beans,这样我们可以直接访问到它们。
- <?variable-resolver class="org.zkoss.zkplus.spring.DelegatingVariableResolver"?>
import 指令:引入在另一个zuml页面中的组件定义和初始化器,即从指定的页面引入component指令和init指令,注意:除了这两个指令外的其它指令均 被忽略,以免混淆。其典型的应用是将一套组件定义在一个zuml页面中,然后在其它的zuml页面中引入,这样除了系统默认的,可以共享一套相同的组件定 义。
八、zk属性
apply属性:指定一个类或一组类(逗号分隔)用以初始化组件,被指定的类必须实现org.zkoss.zk.ui.util.Composer接口,然后由于组件以及子组件初始化之后会调用doAfterCompose方法,所以我们就可以在这个方法内进行初始化。
use属性:指定一个类(代替默认的)来创建一个组件。
forward属性:将目标组件一个事件以其它事件名称跳转至另一个组件,例如
- <window id="ww">
- <button label="Submit" forward="onClick=ww.onOK"/>
- </window>
九、组件集及XML命名空间
如 前所述,zk使用xml的命名空间区分不同的组件集。但在多数情况下,某些页面仅仅使用一套组件,为了使得这样的组件更容易编写,zk以扩展名为基础决定 了默认的命名空间,例如xul和zul意味着使用XUL命名空间,而对于html、xhtml则默认使用XHTML命名空间。