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命名空間區別它們。