[J2EE] 閒聊 zk 2 導論 2
最近去綠島玩了三天,所以這篇拖的比較晚。(遮臉)
加上寫了第一篇後覺得還缺少一隻ap做說明,得花點時間作一個,
想想目前還是暫時把這系列設定成一週一篇吧,取材跟時間上或許比較充裕些。
這篇我也先用概念來做些講解,能聊什麼就聊些什麼,
實例操作(真的能讓你們自己拿來跑且有趣)的部份,
拉到再下一篇再談。 :D
其實 zk 先瞭解概念再去接觸或許會有趣些,
因為很多世界觀跟原本的網頁有一點點不太一樣。
ok , 咱們接著聊下去,我會盡量讓它有趣一些的。(笑)
上回講到 zk application 能透過在 zul 中,
用 component tag 組合而成的,接下來我們就要來說說 component 的故事。
-----------------------------------------------------
一個 component 在 zk 5 主要會由以下幾樣東西構成
1.伺服器端(這裡是 java 的世界)
component class
event class
2.瀏覽器端(這裡是 javascript+ html+ css 的世界)
javascript widget
其中包含
mold -> 一個 javascript 檔案,用來產生 html
css -> 就像一般網頁的css檔
widget class-> 一個有特殊規範的 javascript object
-----------------------------------------------------
好,看到這裡別急著睡著,
這些鬼名詞你不需要記得,我要說的其實只有一個,
那就是 zk 的 component 會分成伺服器端(server)跟瀏覽器端(client),
而這就是一切有趣事情的開頭,在這裡你一定還不知道有趣之處,
所以接下來讓我們跟著 component 去探險吧。 :)
-----------------------------------------------------
我們還是先從最基本的視覺呈現開始,假設現在有個 zul 是 index.zul ,
(忘了什麼是zul的話,看看 #1CgVo5YY (java),
他像是 zk 世界中的 jsp 。:P)
內容是
-----------------------------------------------------
<div>
<label value="hello" />
</div>
-----------------------------------------------------
現在有使用者連上了伺服器 http://localhost/index.zul
ok , 我們的 web container(這裡先假定是tomcat) ,
很開心的照著我們的設定將這個 url 交給我們的 zk servlet ,
我們的翻譯機就開始忠實地吃著我們的 zul tag ……
以下僅為假想範例虛擬碼,大概描述一下 zk servlet 做啥事...
-----------------------------------------------------
zk 翻譯機(肚子好餓,嚼嚼)
div -> new org.zkoss.zul.Div()
zk翻譯機 (div有小孩耶,嚼嚼)
-> label , value= hello
-> new org.zkoss.zul.Label()
.setValue("hello")
.setParent(div)
翻譯機:哈!吃完了!現在我知道這些東西的結構跟它們的親戚關係了!
-----------------------------------------------------
於是我們就拿到一個 div 中含有一個 label child 的 java 結構,
接著我們把他放到一個叫 desktop 的東西上。:D
在這邊稍微做個說明, zk component 跟 html dom 一樣,
是一個可以有 parent 跟 childrens 的結構,
唯一的限制就是他們都必須至少是 Component 類別。
我們暫時先不要管 desktop 到底是什麼,知道一下有這東西就好,
因為這裡我們產生好這個結構,但是瀏覽器還在等我們回傳 html 給他呀!
我們還是趕緊先餵飽我們的 browser 吧!
再解讀完 zul 結構後,再來溫馨的 servlet 翻譯機,
會把這些結構都趕到真正的網頁原始碼去,並且把他們的定義檔都找出來;
我們先告訴網頁說我們會用到的元素的架構長怎樣,
再透過 json 告訴網頁我們會用到哪些元素跟他們的父子關係,
最後透過瀏覽器組裝成我們要的畫面。
以這個例子來講,我們的 div 將會這樣呈現。
<div id="xxxx" >
/* div 的定義檔說要把他的小孩畫在這裡*/
//label 自己說它想要變成底下的html!
<span class="z-label" id="yyyy" >hello</span>
/* div childrend end */
</div>
-----------------------------------------------------
(謎之音)喂!你繞了這麼長一串還講了一堆我看不懂得東西,
你真的以為寫 java 的人都懂 html 跟 serlvet 呀?
呵呵,這裡的確是比較無聊一些,其實在 zk 中你也會比較少看到這部份,
而這裡也的確是寫給懂 html 跟 js 的人看的,
你可以知道 zk 在呈現畫面上跟傳統的html是如何銜接的,
如果你不懂 html + js ,那你也可以瞭解一下,
從 zul 到 html 看起來很像魔術,但是他們其實是一個個嚴謹實作的結果。
-----------------------------------------------------
其實以上這些東西你都不用管(被打),你要知道的就只是寫 zul ,
接著 component 就會知道該怎麼去跟 browser 溝通,
寫 zul 我覺得會比寫 html 來得簡單很多,特別是牽扯到事件,
小小的學習曲線,換一些比較有趣的玩法,不失為一個好嘗試。
-----------------------------------------------------
其實學 zk 越久,越感嘆於 zk 實在是由每一個小細節堆疊起來的,
就在剛剛其實我們已經談到 zk 中一個很重要而且有趣的點了。
我們到這裡一直都還沒有進入到所謂 ajax ,
因為對我們來講,我們只是寫了一些 zul ,
做了一些看起來很無聊,我用 html 也能幾秒鐘寫好的東西,
其他的什麼也沒做,對吧?:)
那再來就讓我們來聊些更有趣的事情吧!
-----------------------------------------------------
在 zk 中有一系列跟 input 有關的元素,
其中對我們一般系統最常見的莫過於是 button 囉。
假設我希望有個button , 按下 button 跳個顯示視窗提示訊息,
那我在 zul 該怎麼做?
---就這麼簡單 testbutton.zul
<button onClick='alert("hello");' label="hello" />
--
-----------------------------------------------------
謎之音:咦?alert ? 這是 javascript 嗎?
嘿嘿,那我們來看看這段程式碼會發生什麼事情吧!
首先當使用者連上我們的 http://localhost/testbutton.zul
接著 servlet 一如往常的嚼著 button ,(這次的結構看來比較簡單!)
接著把結構放到desktop ,吐出 html 給 browser 。
咦?這個 component 有 onClick 事件耶,
那我要告訴 browser 要注意,當他被按下時我必須要知道,
不然就太對不起使用者的請求了(事件宣告)。 by desktop
說時遲那時快,一個正在體驗的使用者,
迅雷不及掩耳的就拿起滑鼠點~~~了下去。
首先最先反應到的當然是網頁的元素( html dom element ),
接著事件被 client 的 javascript widget 接到,
可是 widget 他並不知道 server 的 component 到底要幹麼,
只知道 desktop 送它給browser時做了記號,
如果 onClick 事件被觸發,他就需要跟 desktop 說一聲。
於是他拿起電話打給了 server 想找它的 desktop ,
xmlhttprequest ----> http://localhost/zkau
^ this is so-called ajax
接著接線生接線了,「唯~~很多人在線上啊,你要找哪個desktop啊?」,
哦,你要找的分機是這個啊,那我想我知道你家的 desktop 了。
zkau -> find the active desktop
desktop:哦,你要找你在伺服器上的button問說到底要幹麼喔,
你等我一下,我再幫你轉接。
desktop -> find the component -> find event handler
onClick 事件處理者:我告訴你~只要呼叫某個好人幫你作一下訊息呈現就好啦~
-> html -> invoke zk alert function
你看吧,其實只是要你跟使用者打個招呼而已,Hello!很簡單吧!
-----------------------------------------------------
你或許會心想:
什麼啊!不過就是 call 一個 jq.alert() 的 javascript 函式,
為什麼要故作玄虛還發個 ajax request 回 server side 啊??
問的好!
在這個例子中我們的確不一定需要做這樣的溝通,
事實上zk有提供直接綁定 client event ,不用回 server side 的作法。
(稱之為 client side programming , 是zk5 的特色之一. )
不過在這裡讓我們發揮一下想像力吧!
假設我們今天要做的不是一個單純的alert,而是這樣的東西呢?
-----------------------------------------------------
<button label="hello" >
<attribute name="onClick">
//myDao 是個假類別,事實上沒有這東西,只是方便說明,
//假設這個 dao 操作會去 count 現在資料庫使用者總數,
//而且他把資料庫的連線資訊都已經包裝起來了。
// 就像是個 java 應用程式
int users = myDao.countUsers();
alert(users);
</attribute>
</button>
-----------------------------------------------------
oops! 看看我們做了什麼好事,
我們竟然在一個button按下去時就做了一次的資料庫查詢,
對我們來講,竟然完全不用管任何跟 request 有關的東西。
而且還不用換頁,可以拿到即時的反應!
-----------------------------------------------------
回頭想想看在傳統 jsp 我們要怎麼樣寫才能做這件事,
首先我們要先寫好一個
<input type="button" value="hello" id="hello" />
我假設你夠聰明已經懂得用 jQuery 包裝你的 ajax ,
(否則你要多寫幾十行就為了一個 request)
/*你得先載入 jQuery */
$("#hello").click(function(){
$.post("data.jsp",function(data){
alert(data);//we use alert instead jq.alert in zk
});
});
接著你要寫 data.jsp 或 servlet ,
裡面寫上
<%
int users = myDao.countUsers();
out.println(users);
//讓我偷懶一下寫 scriptlet,意思到就好~~
%>
-----------------------------------------------------
看起來好像跟 zk 差不多簡單,雖然其實我已經偷偷放水很多了,
像是其實 jQuery 還要另外載入,你也必須要另外寫一些東西才能作到
像 zk 這樣比較精緻的 alert 對話框。
而且最麻煩也最重要的是,這樣的 ajax 很難具有泛用性!
我草擬的這個 jsp ajax request 就只能處理 alert 這件事,
如果我今天 ajax 之後想要多個從server傳回來的 label ,
那我還得改寫我的程式碼才行。
而且我可能還要增加許多零碎的檔案來處理這些分開的回傳值,(data.jsp)
雖然在某些像是 struts 的framework 你有機會再簡化一些,
但是這些零碎的物件管理,仍然或多或少會造成我們coding上的負擔。
這也是我在 2008 年年底這篇文章提到,ajax的各種挑戰中的一個。
#19CbYPzF (Web_Design)
我曾經致力於把 ajax 跟 javascript 應用盡可能的發揮到一個程度,
這些東西有時候是個好東西,有時候又是個折磨人的小妖精,
我相信曾經有過傳統 ajax 開發經驗的人應該對這些都能夠心有戚戚焉。
-----------------------------------------------------
嘿嘿,寫到這裡其實這篇已經接近尾聲,我們一次只前進一些,
zk 是個非常大而且豐富的世界,
我們不用太著急,一步一腳印繼續向前走就是了。
雖然我很想讓你們跟我一樣玩一玩我所看到的有趣世界。:)
it's really interesting.
-----------------------------------------------------
文末我們回頭提到剛剛我們所說得東西,如果按下按鈕後,
要即時增加一個元素在button之後怎麼辦?做得到嗎?
-----------------------------------------------------
<button label="hello" >
<attribute name="onClick">
int users = 5; // let's just use a fake data now
alert(users);
//self means the event target , the button.
self.getParent().appendChild(new Label("i am new!"));
</attribute>
</button>
-----------------------------------------------------
瞧,真的很簡單吧,而且 onClick 裡面的東西,
或許有些人會覺得這看起來像是 javascript, (但int users 漏餡了!)
其實這是象徵標準而嚴謹的 java code。:)
我並不是在開玩笑,上述虛線中的東西是真的合法的 zk code,
你可以在 zk 的網站上試試看他(玩玩看嘛,動動手指不會虧本的!:D)。
按照以下的步驟
1.首先打開 zk sandbox
http://www.zkoss.org/zksandbox/userguide/
2.右下角的畫面有個簡單 window,但是那不重要,有個view source按鈕,
如果你有慧根就看得到,點他一下。
3.你會發現顯示畫面變成一個 textarea,嘿嘿!
你現在可以在這個textarea中打入「你自己的」 zk code了,
酷吧!
4.接著把原本的window code清掉,讓textarea變成空白,
把以下紅字的部份複製貼到textarea上。
(你也可以多寫幾個alert或者改一下數字、字串,這很隨性的。)
<button label="hello" >
<attribute name="onClick">
int users = 5; // let's just use a fake data now
alert(users);
//self means the event target , the button.
self.getParent().appendChild(new Label("i am new!"));
</attribute>
</button>
5.按下底下的try it,你會發現畫面上出現了一個顯示 hello 的button,
按下去時就會執行我們剛剛所寫得 onClick 定義囉!酷吧!
-----------------------------------------------------
其實我們這一張講得都還是一些非常基本而且小的行為,
但是我相信這些已經足夠開始對 zk 的世界有一點點小小的感覺了,
事實上我們會一章一章從比較小的單位,開始進入到比較大的單位,
我也會陸續介紹一些我們過去在 web project 中,
會需要的東西,在 zk 到底要怎麼實現。
如果有想要看什麼主題,也可以提出討論就是了,
不過基本上前五章我想應該都還是圍繞在zk 主體討論。
我們還有非常多的大大小小的有趣東西還沒開始討論呢!
" Magic made of basic. " < 這真是非常的有哲理。^^
TonyQ
--
I am a person, and I am always thinking .
Thinking in love , Thinking in life ,
Thinking in why , Thinking in worth.
I can't believe any of what ,
I am just thinking then thinking ,
but worst of all , most of mine is thinking not actioning...
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 111.71.122.74
※ 編輯: TonyQ 來自: 111.71.122.74 (10/12 23:01)
※ 編輯: TonyQ 來自: 111.71.122.74 (10/12 23:06)
推
10/13 00:17, , 1F
10/13 00:17, 1F
fix some typo
※ 編輯: TonyQ 來自: 220.133.44.37 (10/13 09:40)
推
10/13 14:36, , 2F
10/13 14:36, 2F
→
10/13 15:02, , 3F
10/13 15:02, 3F
※ 編輯: TonyQ 來自: 220.133.44.37 (10/13 15:32)
推
10/14 00:48, , 4F
10/14 00:48, 4F
推
10/14 01:07, , 5F
10/14 01:07, 5F
→
10/14 07:11, , 6F
10/14 07:11, 6F