在laszlo應用開發過程中大部分編碼過程集中在對系統組件的熟練應用比如取值傳值刷新組件狀態等等但是很多情況下尤其是項目的初始編碼階段需要定義一些滿足項目特定要求的界面組件這就需要自定義組件了
自定義組件開發首先需要對lzx的語法系統組件結構開發文檔有全面而且深刻的理解然後通過不斷的鍛煉按照由間到繁的實踐過程才能逐漸成為開發高手
理解組件的基本原理
原理介紹類模型視圖控制器(MVC)
class與組件
LZX語言是一種面向對象的基於原型的編程語言而class是LZX編程語言的核心使用class你可以生成定制的可重用的組件來提高代碼編寫效率(LZX is an objectoriented prototype based language that allows you to create custom reusable classes to streamline and minimize code Classes are at the heart of LZX programming)
下面看看一個簡單的class:
<class name=MyClass width= height= bgcolor=#CFDAB>
<text align=center valign=middle>Hello World!</text>
</class>
這就定義了一個簡單的classclass在LZX語法中繼承自LzView所以它可以有高度寬度背景色等屬性
在canvas裡這樣使用它
<MyClass name=myFirstInstance/>
就是說把已經定義的類名當作一個標簽的名稱放在canvas裡就可以了如果你願意可以給它起個實例名比如myFirstInstance還可以指定它的位置等等
(詳見Software Engineers Guide:Chapter Introduction to Classes and Object Oriented Programming)
這是一個簡單的class但也是一個簡單的組件如果把這個class擴展一下添加一些屬性事件數據模型那麼它就可以構成一個可重用的組件
解析LzButton
一個功能完整的組件應該由個部分組成MVC
M: A model that represents the data for the application
V: The view that is the visual representation of that data
C: A controller that takes user input on the view and translates that to changes in the model
(引自A Swing Architecture Overview)
M表示模型模型代表著組件的數據內容
V表示視圖視圖代表著組件的視覺形象
C表示控制器控制器接收用戶輸入並對其做出響應
下面看看一個Openlaszlo系統組件中最常用也是最簡單的一個組件button
打開C:\Program Files\OpenLaszlo Server \Server\lps\lps\components\lz 下面的buttonlzx
會看到個<include/>標簽這是button組件需要的父類組件
接下來的<resource/>是button組件需要的視圖資源大多是flash圖片背景
注意第行<class name=button extends=basebutton …這才是組件真正定義的開始可以看出button繼承自父類basebutton也就是說button的基本行為來自於basebuttonbasebutton定義了button組件的基礎控制部分即MVC中的C
接下來是一些屬性定義<attribute name=someproperty value=valuecorresponding/>name表示屬性名稱value是對應的值
這些attribute標簽是組件需要的屬性這些屬性一般都要默認的值如果需要修改在使用組件時重載這些屬性就可以了
接下來這些<method name=…/>代表組件的C即控制部分
最後是<view name=…這些代表組件的V視圖部分前面定義的resource在這裡用到
因為按鈕組件不需要數據來填充也就是說它不是用來展現數據所以就沒有M模型部分
解析List
list組件和button組件不同的地方在於它有對其內部數據進行操作的部分即modelM還是在剛才的目錄打開源文件listlzx
在第行<class name=list extends=baselist…可以看出list也是繼承自其父類baselistlzx即list組件的控制部分
當然基礎組件的定義不完全是控制部分也包含部分模型部分但是組件的定義則包含了MVC三個部分
比如baselistlzx中<method name=getSelection>
<method name=getNumItems>
<method name=getItemAt args=index >
<method name=getItem args=value>
<method name=addItem args=text value >
<method name=removeItem args=value >
……
這些都是屬於數據操作部分也定義在了父類中這個沒有嚴格區分
而在listlzx中數據操作只定義了<method name=addItem args=txt val >也是重載了父類的方法
通過superaddItem(txtval)來重新定義了
制作一個簡單的自定義button
通過了解系統組件的結構看來自定義一個組件也不是什麼難事了如何下手做呢還是找個例子先
打開參考文檔找到Base Classes第一個就是basebutton點擊查看說明文檔和例子原來這麼簡單只要給basebutton加上資源 就是一個按鈕了那麼自己再修改一下不就是自己想要的按鈕了嗎?
首先按鈕文字是必須要加的那麼需要一個屬性來保存文本字符
<attribute name=text type=html value=/>
然後需要一個text組件來顯示按鈕文字
<text name=txt align=center valign=middle resize=true fgcolor=# text=${parenttext}/>
接下來需要添加鼠標事件來讓按鈕上的文字做出點擊響應
<method event=onmousedown>
txtsetX(txtx+)
txtsetY(txty+)
</method>
<method event=onmouseup>
txtsetX(txtx)
txtsetY(txty)
</method>
這樣就完成了一個具備基本功能的按鈕了
<class name=mybutton width= height= extends=basebutton resource=longbtn_rsc>
<attribute name=text type=html value=/>
<text name=txt align=center valign=middle resize=true fgcolor=# text=${parenttext}/>
<method event=onmousedown>
txtsetX(txtx+)
txtsetY(txty+)
</method>
<method event=onmouseup>
txtsetX(txtx)
txtsetY(txty)
</method>
</class>
在canvas裡通過<mybutton name=buttonname text=clickMe>
<handler name=onclick>
//do something;
</handler>
</mybutton>
就可以使用了
擴展一個系統組件
在開發RIA項目時往往會遇到比較復雜的業務需求或者大數據量展現等任務這時能滿足這些任務的組件就顯得分外重要筆者在開發第一個任務時需要在tree組件上進行操作而這個tree的節點又很多視圖的渲染過程往往花費十幾秒以上有時竟然讓IE崩潰郁悶之極
幸得網友的指點
找到一個lazytree組件
才解決了這個問題
這是一個擴展了系統tree組件功能的組件
它重載了tree節點生成的過程
由原來得一次全部生成
變成逐步生成
大大降低了初始渲染時間
<class name=
lazytree
extends=
tree
>
<!
Turn off auto
recursion for tree
Get child nodes when tree is opened
>
<attribute name=
recurse
value=
false
type=
boolean
/>
<attribute name=
haveChildren
value=
false
type=
boolean
/>
<method event=
onopen
args=
o
><![CDATA[
// If we already have children
don
t fetch them again
if (this
haveChildren) return;
if (o) {
// Now set recurse to true
This value is used in basetree
s
// createChildTrees() method
See
// lps/components/base/basetree
lzx for and
// lps/components/lz/treee
lzx source code
this
setAttribute(
recurse
true)
createChildTrees()
this
setAttribute(
recurse
false)
// We have child nodes
this
setAttribute(
haveChildren
true)
}
]]></method>
</class>
如注釋所書
Turn off auto
recursion for tree
Get child nodes when tree is opened
關閉了自動遞歸過程
只有當前節點打開時
生成下一級節點
由此可見
理解系統組件的結構和原理
是何等重要!
開發高級的自定義組件
表格是界面開發常用的組件
但是laszlo的grid不夠漂亮和精練
所以構建自己的grid就顯得必要了
以openria網站的資源下載表格為例
需要
列
而且有一列要能提供下載內容的點擊操作
經過構思
步驟如下
第一步
構建表格體包括表頭和表體
<view name=
header
…
<text x=
text=
ID
/>
<text x=
text=
名稱
/>
<text x=
text=
描述
/>
<text x=
text=
分類
/>
<text x=
text=
鏈接
/>
</view>
<view name=
rowcontainer
…
<view name=
columns
…
…
</view>
第二步
構建表格頭背景和表格體中的行
表頭背景
<view name=
bg
width=
$once{parent
width}
…
<view name=
whitebg
x=
y=
…
動態行
<view name=
columns
datapath=
${parent
datapath}
width=
$once{parent
width
}
>
<simplelayout axis=
y
spacing=
/>
<view datapath=
*
…
<text x=
datapath=
@id
width=
/>
<text x=
datapath=
@name
width=
/>
…
</view>
第三步
添加事件和滾動條
<text x=
datapath=
@status
width=
fgcolor=
#
ff
>
<method event=
onclick
>
</method>
<method event=
onmouseover
>
</method>
<method event=
onmouseout
>
</method>
</text>
滾動條
<scrollbar/>
最後完成的組件代碼是
<class name=
downloadgrid
datapath=
width=
height=
>
<view name=
bg
width=
$once{parent
width}
height=
$once{parent
height}
bgcolor=
#
/>
<view name=
whitebg
x=
y=
width=
$once{parent
width
}
height=
$once{parent
height
}
bgcolor=
#FFFFFF
/>
<view name=
header
x=
y=
width=
$once{parent
width
}
height=
bgcolor=
#
CEFA
>
<text x=
text=
ID
/>
<text x=
text=
名稱
/>
<text x=
text=
描述
/>
<text x=
text=
分類
/>
<text x=
text=
鏈接
/>
</view>
<view name=
rowcontainer
x=
y=
datapath=
${parent
datapath}
width=
$once{parent
width
}
height=
$once{parent
height
}
clip=
true
>
<view name=
columns
datapath=
${parent
datapath}
width=
$once{parent
width
}
>
<simplelayout axis=
y
spacing=
/>
<view datapath=
*
width=
$once{parent
width}
height=
bgcolor=
#F
F
F
>
<text x=
datapath=
@id
width=
/>
<text x=
datapath=
@name
width=
/>
<text x=
datapath=
@describe
width=
/>
<text x=
datapath=
@category
width=
/>
<text x=
datapath=
@status
width=
fgcolor=
#
ff
>
<method event=
onclick
>
var hashref = parent
datapath
p
hasAttr(
href
)
if(hashref){
var address = parent
datapath
p
getAttr(
href
)
LzBrowser
loadURL(address
_blank
)
}
</method>
<method event=
onmouseover
>
this
setColor(
x
)
</method>
<method event=
onmouseout
>
this
setColor(
x
FF)
</method>
</text>
</view>
</view>
<scrollbar/>
</view>
</class>
總結
組件是laszlo應用的重要組成部分
每次的項目開發都會涉及到組件的開發
而且關系到項目產品的質量和效果
這也是考驗一個RIA開發人員水平的重要依據
laszlo的demo中有很多值得研究的組件
網上也有開發人員的作品供大家分享
每次openlaszlo新版本的發布都會有新的組件添加進來
這要感謝眾多contributor的慷慨
開源軟件正是在這種開放的環境中不斷成長起來的
讓我們寫好laszlo組件
共同促進RIA的發展
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26830.html