ZK 6中的MVVM初探
在上一篇文章中,我們已經(jīng)看到Ajax框架ZK如何采用CSS選擇器啟發(fā)的Controller來(lái)在View中連接UI組件并監(jiān)聽(tīng)它們的事件。 在此ZK MVC模式下, View中的UI組件無(wú)需綁定到任何Controller方法或數(shù)據(jù)對(duì)象。 使用選擇器模式作為將View狀態(tài)和事件映射到Controller的靈活性,使代碼更適應(yīng)更改。
MVVM在相反方向上實(shí)現(xiàn)關(guān)注點(diǎn)分離。 在這種模式下,視圖模型和綁定器機(jī)制代替了控制器。 綁定器將View的請(qǐng)求映射到View-Model中的動(dòng)作邏輯,并更新雙方的任何值(數(shù)據(jù)),從而允許View-Model獨(dú)立于任何特定的View。
ZK 6中的MVVM的剖析
以下是ZK 6的MVVM模式的示意圖:
以下是圖中未傳達(dá)的一些其他要點(diǎn):
BindComposer:
- 實(shí)現(xiàn)ZK的標(biāo)準(zhǔn)控制器接口(Composer&ComposerExt)
- 默認(rèn)實(shí)現(xiàn)就足夠了,不需要修改
視圖:
- 通知活頁(yè)夾調(diào)用哪種方法以及在視圖模型上更新哪些屬性
視圖模型:
- 只是一個(gè)POJO
- 通過(guò)Java注釋與活頁(yè)夾進(jìn)行通信
MVVM運(yùn)行中
考慮在不知道確切的UI標(biāo)記的情況下顯示簡(jiǎn)化清單的任務(wù)。 庫(kù)存是項(xiàng)目的集合,因此我們具有以下對(duì)象的表示形式:
public class Item {private String ID;private String name;private int quantity;private BigDecimal unitPrice;//getters & setters }期望可以選擇并操作列表中的項(xiàng)目也很有意義。 因此,根據(jù)到目前為止的知識(shí)和假設(shè),我們可以繼續(xù)執(zhí)行視圖模型。
public class InventoryVM {ListModelList<Item> inventory;Item selectedItem;public ListModelList<Item> getInventory(){inventory = new ListModelList<Item>(InventoryDAO.getInventory());return inventory;}public Item getSelectedItem() {return selectedItem;}public void setSelectedItem(Item selectedItem) {this.selectedItem = selectedItem;}}在這里,我們?yōu)閂iew-Model實(shí)現(xiàn)提供了一個(gè)典型的POJO,以及帶有其getter和setter的數(shù)據(jù)。
查看實(shí)施,“采取行動(dòng)”
現(xiàn)在,假設(shè)我們后來(lái)了解到View的要求只是一個(gè)簡(jiǎn)單的表格顯示:
實(shí)現(xiàn)上述UI的可能標(biāo)記是:
<window title='Inventory' border='normal' apply='org.zkoss.bind.BindComposer' viewModel='@id('vm') @init('lab.zkoss.mvvm.ctrl.InventoryVM')' ><listbox model='@load(vm.inventory)' width='600px' ><auxhead><auxheader label='Inventory Summary' colspan='5' align='center'/> </auxhead><listhead><listheader width='15%' label='Item ID' sort='auto(ID)'/><listheader width='20%' label='Name' sort='auto(name)'/><listheader width='20%' label='Quantity' sort='auto(quantity)'/><listheader width='20%' label='Unit Price' sort='auto(unitPrice)'/><listheader width='25%' label='Net Value'/></listhead><template name='model' var='item'><listitem><listcell><label value='@load(item.ID)'/></listcell><listcell><label value='@load(item.name)'/></listcell><listcell><label value='@load(item.quantity)'/></listcell><listcell><label value='@load(item.unitPrice)'/></listcell><listcell><label value='@load(item.unitPrice * item.quantity)'/></listcell></listitem> </template></listbox> </window>讓我們?cè)谶@里詳細(xì)說(shuō)明一下標(biāo)記。
- 在第1行,我們將默認(rèn)的BindComposer應(yīng)用于Window組件,該組件使Window的所有子組件均受BindComposer的影響。
- 在下一行,我們指示BindComposer實(shí)例化哪個(gè)View-Model類,并為View-Model實(shí)例提供ID,以便我們對(duì)其進(jìn)行引用。
- 由于我們正在將數(shù)據(jù)集合加載到列表框,因此在第3行,我們將View-Model實(shí)例的屬性“庫(kù)存”(即Item對(duì)象的集合)分配給列表框的屬性“模型”。
- 然后,在第12行,我們?cè)谀0褰M件上使用該模型。 模板根據(jù)收到的模型迭代其封閉的組件。 在這種情況下,我們有5個(gè)列表項(xiàng),它們?cè)诹斜砜蛑薪M成一行。
- 在每個(gè)Listcell中,我們加載每個(gè)對(duì)象的屬性并將其顯示在Labels中。
通過(guò)ZK的綁定系統(tǒng),我們能夠訪問(wèn)View-Model實(shí)例中的數(shù)據(jù),并使用批注將其加載到View中。
查看實(shí)施,“采取兩個(gè)”
假設(shè)在以后的開(kāi)發(fā)中,我們同意當(dāng)前的表格顯示在我們的演示文稿中占用了太多空間,并且現(xiàn)在要求我們僅在組合框中選擇該項(xiàng)目時(shí)才顯示該項(xiàng)目的詳細(xì)信息,如下所示:
盡管表示和行為(僅在用戶選擇時(shí)才顯示詳細(xì)信息)與我們以前的實(shí)現(xiàn)有所不同,但是View-Model類不需要大量修改。 由于僅當(dāng)在組合框中選中某個(gè)項(xiàng)目的細(xì)節(jié)時(shí)才會(huì)顯示它的細(xì)節(jié),所以很明顯,我們需要處理'onSelect'事件,讓我們添加一個(gè)新方法doSelect :
public class InventoryVM {ListModelList<Item> inventory;Item selectedItem;@NotifyChange('selectedItem')@Commandpublic void doSelect(){ }//getters & setters}在我們的例子中,用@Command注釋的方法使其有資格通過(guò)其名稱從我們的標(biāo)記中調(diào)用:
<combobox onSelect='@command('doSelect')' >注釋@NotifyChange('selectedItem')允許用戶在組合框中選擇新項(xiàng)目時(shí)自動(dòng)更新selectedItem屬性。 出于我們的目的,方法doSelect不需要其他實(shí)現(xiàn)。 完成這些更改后,我們現(xiàn)在可以看到經(jīng)過(guò)稍微修改的View-Model如何與我們的新標(biāo)記一起工作:
<window title='Inventory' border='normal' apply='org.zkoss.bind.BindComposer' viewModel='@id('vm') @init('lab.zkoss.mvvm.ctrl.InventoryVM')' width='600px'>...<combobox model='@load(vm.inventory)' selectedItem='@bind(vm.selectedItem)' onSelect='@command('doSelect')' ><template name='model' var='item'><comboitem label='@load(item.ID)'/></template><comboitem label='Test'/></combobox><listbox visible='@load(not empty vm.selectedItem)' width='240px'><listhead><listheader ></listheader><listheader ></listheader></listhead><listitem><listcell><label value='Item Name: ' /></listcell><listcell><label value='@load(vm.selectedItem.name)' /></listcell></listitem><listitem><listcell><label value='Unit Price: ' /></listcell><listcell><label value='@load(vm.selectedItem.unitPrice)' /></listcell></listitem><listitem><listcell><label value='Units in Stock: ' /></listcell><listcell><label value='@load(vm.selectedItem.quantity)' /></listcell></listitem><listitem><listcell><label value='Net Value: ' /></listcell><listcell><label value='@load(vm.selectedItem.unitPrice * vm.selectedItem.quantity)' /></listcell></listitem></listbox>... </window>- 在第4行,我們將數(shù)據(jù)收集清單加載到Combobox的model屬性,以便它可以使用在第7行聲明的Template組件迭代顯示數(shù)據(jù)模型中每個(gè)Item對(duì)象的ID。
- 在第5行,selectedItem屬性指向該Item對(duì)象列表上最近選擇的Item。
- 在第6行,我們已將onSelect事件映射到View-Model的doSelect方法
- 在第12行,僅當(dāng)View-Model中的selectedItem屬性不為空時(shí),才使包含項(xiàng)明細(xì)的列表框可見(jiàn)(在組合框中選擇一個(gè)項(xiàng)之前,selectedItem將保持為空)。
- 然后加載selectedItem的屬性以填充列表框。
概括
在MVVM模式下,我們的View-Model類將其數(shù)據(jù)和方法公開(kāi)給活頁(yè)夾; 沒(méi)有參考任何特定的View組件。 View實(shí)現(xiàn)通過(guò)綁定器訪問(wèn)數(shù)據(jù)或調(diào)用事件處理程序。
在本文中,我們僅介紹ZK的MVVM機(jī)制的基本原理。 活頁(yè)夾顯然不僅限于從視圖模型中加載數(shù)據(jù)。 除了將數(shù)據(jù)從View保存到ViewModel之外,我們還可以混合使用View to View-Model通信來(lái)注入數(shù)據(jù)轉(zhuǎn)換器和驗(yàn)證器。 MVVM模式也可以與MVC模型結(jié)合使用。 也就是說(shuō),如果我們?cè)敢獾脑?#xff0c;我們也可以通過(guò)MVC Selector機(jī)制連接組件并監(jiān)聽(tīng)觸發(fā)事件。
我們稍后將深入探討其中一些主題。
參考:我們的JCG合作伙伴 Lance Lu在Tech Dojo博客上對(duì)ZK 6中的MVVM進(jìn)行了初步了解 。
翻譯自: https://www.javacodegeeks.com/2012/06/first-look-at-mvvm-in-zk-6.html
總結(jié)
以上是生活随笔為你收集整理的ZK 6中的MVVM初探的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 比较OpenDDR和WURFL
- 下一篇: Maven的鸟瞰图