zk体系结构:
     zk内嵌了体格基于ajax的机制进行自动的交互,一个基于xul的组件丰富可用性,一个标记语言简化开发。
     基于ajax的机制包含了三部分。 zk loader,zk au engine和zk client engine.对于用户的请求,zk loader加载zk page,然后转换成html page,发回客户端。一张zk page 是用zuml标记语言写的。zuml,类似与html,是用来描述创建什么组件,如何表现组件的。这些组件,一旦创建了,在session超时前都保持可用。
     zk au engine 和 zk client engine 的工作方式类似于棒球场上的投手和接球手。他们向服务器上正在运行的应用传递在浏览器中正在发生的事件,基于服务器操纵组件的规则更新dom树。这也被称为事件驱动的编程模式。
    工作流程:
     1.当用户在浏览器中输入了url或者点击了超级链接,一个请求发送到了服务器。如果rul满足条件(需要zk loader),zk loader被调用进行处理请求。
     2.zk loader加载指定的page,翻译page创建指定的组件。
     3.翻译完了整张页面以后,zk loader 将结果转成一张html page。这张page被发送到有zk client engine的浏览器。
     4.zk client engine安静的在浏览器中侦察用户触发的时间,如移动鼠标,修改值什么的,一旦侦察到了,它就通过发送zk 请求唤醒zk au engine。
     5.从client engine那接受到zk请求后,在必要的情况下,au engine 更新相应组件的内容。然后,au engine唤醒应用中相关是事件处理器。
     6.如果应用选择修改,增加,移除组件的内容,au engine通过zk回应发送被改变的组件的新的内容到client engine.
     7.这些zk回应指导client engine如何去更新dom树。
   
组件,页面和桌面
    组件:一个组件就是是一个UI 对象,如label,button,tree.它定义了用户接口的视图和动作。通过操纵它们,程序员控制如何在客户端上展现应用。一个组件必须扩展org.zkoss.zk.ui.Component接口。
    页面:一张页面是组件的集合。页面配置了属于它的组件,定义了组件在浏览器中出现的位置。当zk loader解释zuml page时,页面被自动创建。
    桌面:一张zuml page可能间接或直接的包含其他的 zuml page。当对于一个url 请求创建了多个页面的时候,它们被称为桌面(org.zkoss.zk.ui.Desktop).即桌面就是服务于同一个url的页面集合。
     当zk应用运行的时候,桌面上可能多个页面被加入或删除,就如同页面上的组件被增加或删除类似。
     createComponent方法:
     注意页面和桌面都是在后台创建和删除。但是没有api去创建和删除他们。页面创建是每次zuml加载的时候。页面删除是zk发现它再也不被关联的时候。桌面创建是在第一次zuml page加载的时候,删除是在太多的桌面在指定的session中创建的时候。
     org.zkoss.zk.ui.Executions类中createComponents方法只能创建组件而不是方法,即使是在加载zuml文档的时候。
组件的森林
     一个组件至多有一个父亲,可能有多个孩子。一些组件只接受特定类型的组件作为孩子,而一些组件只能成为特定组件的孩子,而有些却不允许有任何孩子。举例来说,xul的listbox只接受Listcols和Listiterm。
     一个没有父亲的组件被称为根组件。一个页面可能含有多个根组件,可以通过getRoots函数得到。
    组件:一个视图和java对象
     除了作为服务器上的一个java对象,组件也在浏览器扮演了视图角色,当且仅当它属于页面的时候。当组件与页面关联的时候,它的视图部分就被创建了。当组件不和页面关联的时候,其视图部分也被移除了。
     有两个方法可以放组件关联到页面。1.你可以调用setPage方法使一个组件成为指定页面的根组件。2.你可以调用setParent,insertBefore或者 appendChild方法使之成为其他组件的孩子。
     类似的,你可以通过setPage函数设置null把根组件从页面分离。当然,其孩子也和页面分离了。
    标示符:
     每一个组件都含有一个标示符(可以通过getId获得).它是组件被创建的时候自动获得的。程序员可以在任何时候修改它,没有任何限制。可是,一旦一个标示符被指定了,程序员可以在zuml page中通过java 代码或el表达式进入它。
<window title="Vote" border="normal">
Do you like ZK? <label id="label"/>
<separator/>
<button label="Yes" onClick="label.value = self.label"/>
<button label="No" onClick="label.value = self.label"/>
</window>
    UUID:
     一个组件有另一个标示符叫做UUID(Unicersal Unique ID),这个才是程序员真正需要的。
     在浏览器组件和client engine通过UUID来操纵dom,和与服务器通信。其实,dom元素的id属性就是UUID.
     UUID是在组件被创建的时候生成的。它是不可变的,except the identifiers of components for representing HTML tags.  
     HTML相关的组件处理UUID和其他的组件不同:UUID和ID是相同的。如果你修改HTML相关的组件de   ID,则UUID也会被相应的修改。所以,旧试的javascript代码和servlet仍旧不加修改的保持工作。
     THE ID SPACE:
     将一个完整的视图分解成多个zuml页面是很普通的做法。举个例子,一个页面来显示订购单,一个对话狂用来输入支付条件。如果所有的组件在同一个桌面上有唯一的标示的话,程序员必须在所有的页面在一个桌面上保持这种唯一性。
     引入ID空间来解决这个问题。ID空间是桌面组件的子集。唯一性只需要在ID空间上面得到保证即可。
     一种简单的ID空间的形式是window(org.zkoss.zul.Window).window的所有子孙组件(包括window自己)形成一个独立的ID空间。因此,你只需要在页面上使用window作为组件的最上级,这样程序员就可以保持页面独立的唯一性。
     更一般的情况,任何组件可以形成一个ID空间,只要实现了org.zkoss.zk.ui.IdSpace接口。页面也实现这个接口,所以它也是空间的所有者。
     ID空间的最顶端组件也称为ID空间的所有者,可以通过component接口的getSpaceOwner方法返回。可以通过getFellow方法得到同个空间的成员。
     值得注意的是,getFellow方法可以由空间中的所有成员使用。getSpaceOwner方法也是的。
     The org.zkoss.zk.ui.Path class provides utilities to simplify the location of a component among ID spaces. Its use is similar to java.io.File.
      Path.getComponent("/A/C/E");
new Path("A/C", "E").getComponent();
     在zscript中定义变量和函数
<window id="A>
<zscript>
Object myvar = new LinkedList();
void myfunc() {
...
}
</zscript>
...
<button label="add" onClick="myvar.add(some)"/>
<button label="some" onClick="myfunc()"/>
</window>
     定义的变量和函数被存储在包含他们的ID空间中,在上面的情况下,myvar和myfunc都存储在window a中。
     子空间可以看见父空间中定义的变量和函数。
     有意思的是,当assignment发生时,zk会首先定位变量。如果找到了,马上更新。如果没有找到,则新建一个变量。所以,在下面的例子中var2是”def“,而第二个var1和第一个是相同的。
<window id="A">
<zscript>var1 = "abc";</zscript>
<window id="B">
<zscript>var1 = "def";</zscript>
</window>
<zscript>var2 = var1;</zscript>
</window>
To declare a variable local to a namespace no matter its parent ID space defined it or not,use the following format:
MyClass myvar = myvalue,所以,在下面的例子中,var2是"abc"。in other words,the second var1 is created in the id space of window b,while the first var1 is created in the id space of window a.
<window id="A">
<zscript>var1 = "abc";</zscript>
<window id="B">
<zscript>Object var1 = "def";</zscript>
</window>
<zscript>var2 = var1;</zscript>
</window>
    zscript 和 el 表达式
     在zscript中定义的变量是能够被el表达式看见的,只要他们在一个id空间中。
<window>
<zscript>
String var = "abc";
</zscript>
${var}
</window>

<window>
abc
</window>
效果相同
     下面的变量在同一个空间中的是看不见的,它们被{}包围了
<zscript>
{
String var = "abc"; //visible only inside of the curly brace
}
</zscript>
事件:
     事件(org.zkoss.zk.ui.event.Event)是用来通知应用发生了什么。每一个事件被不同的类描述。举个例子,org.zkoss.zk.ui.event.MouseEvent表示了鼠标的动作,像单击。
     为了对事件做出回应,应用必须在事件上注册一个或多个监听。有两中方法。1.指定onXXX在标记语言中。2.给组件调用addEventListener方法。
      作为补充org.zkoss.zk.ui.event.Event类有sendEvent()和postEvent()方法。
    桌面和事件处理
     像上面提到的,桌面是服务于一个url请求的页面的集合。一个桌面也是一个事件监听可以进入的范围。        一个事件是和特定的桌面联系在一起的。zk基于关联的桌面隔离事件,将事件压入隔离的队列。因此,一个桌面的事件被顺序的处理。即,不同桌面的事件的执行关系是水平的。
     一个事件的监听器被允许进入关联的桌面的页面的任何一个组件。也被允许从一个组件转移到另一个组件上,只要是在同一个桌面上。换句话说,它不能访问其他桌面的组件。
    桌面和组件的创建
     当在一个监听器里创建了一个组件。默认的,它被指派到执行事件相关的桌面。这个指派甚至在组件没有关联到页面也会发生。这意味着,在事件监听器中产生的组件在监听器所关联的桌面上是可以被使用的。
     当一个组件不在事件监听器中产生,它不属于任何桌面。在这种情况下,你可以关联到任何桌面只要关联发生在适当的事件监听器内。当然,一旦关联建立了,它就永远属于那个桌面了。
     在大多数应用中,很少有必要在非监听器中创建组件。可是,如果你有一个费时的操作,你可能想在后台线程中行它。然后你可能在后台准备一个组件树,当有适当的时间发生的时候把树添加到桌面上。有关long operations,请参考event listening and processing 。
    zuml和xml命名空间
     zuml是基于xml格式的语言,开发者用来描述视图的。不同的组件集合,像xul,xhtml可以被同时再一个zuml页面中使用。different markup languages could be added transparantly.如果2个或更多的组件集合被应用到同一个page,程序员需要通过xml命名空间区别它们。