ZK 6中的MVVM初探

MVVM与MVC

在上一篇文章中,我们已经看到Ajax框架ZK如何采用CSS选择器启发的Controller来在View中连接UI组件并监听它们的事件。 在此ZK MVC模式下, View中的UI组件无需绑定到任何Controller方法或数据对象。 使用选择器模式作为将View状态和事件映射到Controller的灵活性,使代码更适应更改。

MVVM在相反方向上实现关注点分离。 在这种模式下,视图模型和绑定器机制代替了控制器。 绑定器将View的请求映射到View-Model中的动作逻辑,并更新双方的任何值(数据),从而允许View-Model独立于任何特定的View。

ZK 6中的MVVM的剖析

以下是ZK 6的MVVM模式的示意图:

以下是图中未传达的一些其他要点:
BindComposer:

  • 实现ZK的标准控制器接口(Composer&ComposerExt)
  • 默认实现就足够了,不需要修改

视图:

  • 通知活页夹调用哪种方法以及在视图模型上更新哪些属性

视图模型:

  • 只是一个POJO
  • 通过Java注释与活页夹进行通信

MVVM运行中

考虑在不知道确切的UI标记的情况下显示简化清单的任务。 库存是项目的集合,因此我们具有以下对象的表示形式:

public class Item {private String ID;private String name;private int quantity;private BigDecimal unitPrice;//getters & setters
}

期望可以选择并操作列表中的项目也很有意义。 因此,根据到目前为止的知识和假设,我们可以继续执行视图模型。

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;}}

在这里,我们为View-Model实现提供了一个典型的POJO,以及带有其getter和setter的数据。

查看实施,“采取行动”

现在,假设我们后来了解到View的要求只是一个简单的表格显示:

实现上述UI的可能标记是:

<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>

让我们在这里详细说明一下标记。

  • 在第1行,我们将默认的BindComposer应用于Window组件,该组件使Window的所有子组件均受BindComposer的影响。
  • 在下一行,我们指示BindComposer实例化哪个View-Model类,并为View-Model实例提供ID,以便我们对其进行引用。
  • 由于我们正在将数据集合加载到列表框,因此在第3行,我们将View-Model实例的属性“库存”(即Item对象的集合)分配给列表框的属性“模型”。
  • 然后,在第12行,我们在模板组件上使用该模型。 模板根据收到的模型迭代其封闭的组件。 在这种情况下,我们有5个列表项,它们在列表框中组成一行。
  • 在每个Listcell中,我们加载每个对象的属性并将其显示在Labels中。

通过ZK的绑定系统,我们能够访问View-Model实例中的数据,并使用批注将其加载到View中。

查看实施,“采取两个”

假设在以后的开发中,我们同意当前的表格显示在我们的演示文稿中占用了太多空间,并且现在要求我们仅在组合框中选择该项目时才显示该项目的详细信息,如下所示:

尽管表示和行为(仅在用户选择时才显示详细信息)与我们以前的实现有所不同,但是View-Model类不需要大量修改。 由于仅当在组合框中选中某个项目的细节时才会显示它的细节,所以很明显,我们需要处理'onSelect'事件,让我们添加一个新方法doSelect

public class InventoryVM {ListModelList<Item> inventory;Item selectedItem;@NotifyChange('selectedItem')@Commandpublic void doSelect(){ }//getters & setters}

在我们的例子中,用@Command注释的方法使其有资格通过其名称从我们的标记中调用:

<combobox onSelect='@command('doSelect')' >

注释@NotifyChange('selectedItem')允许用户在组合框中选择新项目时自动更新selectedItem属性。 出于我们的目的,方法doSelect不需要其他实现。 完成这些更改后,我们现在可以看到经过稍微修改的View-Model如何与我们的新标记一起工作:

<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行,我们将数据收集清单加载到Combobox的model属性,以便它可以使用在第7行声明的Template组件迭代显示数据模型中每个Item对象的ID。
  • 在第5行,selectedItem属性指向该Item对象列表上最近选择的Item。
  • 在第6行,我们已将onSelect事件映射到View-Model的doSelect方法
  • 在第12行,仅当View-Model中的selectedItem属性不为空时,才使包含项明细的列表框可见(在组合框中选择一个项之前,selectedItem将保持为空)。
  • 然后加载selectedItem的属性以填充列表框。

概括

在MVVM模式下,我们的View-Model类将其数据和方法公开给活页夹; 没有参考任何特定的View组件。 View实现通过绑定器访问数据或调用事件处理程序。

在本文中,我们仅介绍ZK的MVVM机制的基本原理。 活页夹显然不仅限于从视图模型中加载数据。 除了将数据从View保存到ViewModel之外,我们还可以混合使用View to View-Model通信来注入数据转换器和验证器。 MVVM模式也可以与MVC模型结合使用。 也就是说,如果我们愿意的话,我们也可以通过MVC Selector机制连接组件并监听触发事件。

我们稍后将深入探讨其中一些主题。

参考:我们的JCG合作伙伴 Lance Lu在Tech Dojo博客上对ZK 6中的MVVM进行了初步了解 。


翻译自: https://www.javacodegeeks.com/2012/06/first-look-at-mvvm-in-zk-6.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/372255.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

消失循环的2023?你都做了什么? | 2023 年度总结

2023年度总结 -- 今年都做了什么事&#xff1f; 前言心态关键词感悟 记录申请软著独立游戏技术成长 共勉 前言 又到了一年一次年度总结的时候了。我们常常感叹时间飞逝&#xff0c;却又没办法让它放慢的脚步。那就将2023写下来&#xff0c;让它在时间的长河中留下一丝记忆。 心…

由于SSH配置文件的不匹配,导致的Permission denied (publickey)及其解决方法

读者如要转载&#xff0c;请标明出处和作者名&#xff0c;谢谢。 地址01&#xff1a;http://space.itpub.net/25851087 地址02&#xff1a;http://www.cnblogs.com/zjrodger/ 作者名&#xff1a;zjrodger 【问题发生环境和相关参数】(1)OS&#xff1a;Win7 32Bit. (2)Git&#…

java语言基本语法_Java语言基本语法

Java语言基本语法一、标识符和关键字标识符在java语言中&#xff0c;用来标志类名、对象名、变量名、方法名、类型名、数组名、包名的有效字符序列&#xff0c;称为“标识符”&#xff1b;标识符由字母、数字、下划线、美元符号组成&#xff0c;且第一个字符不能是数字&#xf…

Maven的鸟瞰图

我们每天要做的一件事是使用Maven通过发出诸如mvn install之类的构建命令来构建我们的项目。 然后&#xff0c;Maven查看我们项目的配置文件&#xff08;亲切地称为POM&#xff09;&#xff0c;神奇地找出要执行的操作&#xff0c;并且&#xff0c;嘿&#xff0c;您的构建已完成…

node源码详解(五)

本作品采用知识共享署名 4.0 国际许可协议进行许可。转载保留声明头部与原文链接https://luzeshu.com/blog/nodesource5 本博客同步在https://cnodejs.org/topic/56ed6735b705742136388fa6 本博客同步在http://www.cnblogs.com/papertree/p/5295344.html 在上一篇博客&#xff…

分层图+最短路算法 BZOJ 2763: [JLOI2011]飞行路线

2763: [JLOI2011]飞行路线 Time Limit: 10 Sec Memory Limit: 128 MBDescription Alice和Bob现在要乘飞机旅行&#xff0c;他们选择了一家相对便宜的航空公司。该航空公司一共在n个城市设有业务&#xff0c;设这些城市分别标记为0到n-1&#xff0c;一共有m种航线&#xff0c;每…

java web 保护_java web项目请求控制及简单漏洞防范

背景&#xff1a;当时项目没用什么框架&#xff0c;过滤器&#xff0c;请求限制等都需要自己手写。1、请求加时间戳在后台过滤器中可以加判断&#xff0c;如果请求时间戳与服务器时间相差太大&#xff0c;可以返回异常&#xff0c;具体情况可以具体使用。请求中加时间戳的示例如…

Maven最佳实践

尽管Maven提供了“配置之上的约定”解决方案&#xff0c;但是仍然有足够多的必要配置引起严重的头痛。 在这篇文章中&#xff0c;我将与您分享一些最佳实践&#xff0c;以简化对POM文件的维护。 请勿使用已弃用的引用&#xff0c;例如$ {artifactId}或$ {pom.artifactId}。 使用…

51Nod - 1381 硬币游戏

51Nod - 1381 硬币游戏 有一个简单但是很有趣的游戏。在这个游戏中有一个硬币还有一张桌子&#xff0c;这张桌子上有很多平行线&#xff08;如下图所示&#xff09;。两条相邻平行线之间的距离是1&#xff0c;硬币的半径是R&#xff0c;然后我们来抛硬币到桌子上&#xff0c;抛…

Android中Activity和Fragment之间的通信

Android中Activity和Fragment之间的通信 Fragment启动Activity传数据到Fragment 举例&#xff1a;城市选择列表。一个Fragment启动Activity&#xff0c;Activity再把城市选择数据回传到Fragment中。Fragment中方法iv_city.setOnClickListener(new View.OnClickListener() {Ove…

NoSQLUnit 0.3.0发布

介绍 单元测试是一种验证应用程序中可测试的最小部分的方法。 单元测试必须遵循FIRST规则&#xff1b; 这些是快速&#xff0c;隔离&#xff0c;可重复&#xff0c;自我验证和及时的。 考虑到没有持久层&#xff08;典型的关系数据库或新的NoSQL数据库&#xff09;的JEE应用程…

proftpd java_Proftpd:编译安装

下载 proftpd# wget ftp://ftp.proftpd.org/distrib/source/proftpd-1.3.5a.tar.gz# wget https://github.com/proftpd/proftpd/archive/v1.3.5a.tar.gz# yum -y install gcc openssl-devel# ./configure --prefix/usr/local/proftpd/ \--sysconfdir/usr/local/proftpd/ \--ena…

javascript 相关小的知识点集合

本文主要是列出一些javascript 相关的&#xff0c;不限于javascript的&#xff0c;容易记错或者遗忘的小知识&#xff0c;小技巧。 1、javascript中的false 在 JavaScript&#xff0c;常见的 false 值&#xff1a; 0, 0, 0, -0, false, ,null,undefined,NaN 要注意空数组([])和…

AOS – 另外一个独特的页面滚动动画库(CSS3)

AOS 是一个用于在页面滚动的时候呈现元素动画的工具库&#xff0c;你可能会觉得它和 WOWJS 一样&#xff0c;的确他们效果是类似的。但是AOS是 CSS3 动画驱动的库&#xff0c;当你滚动页面的时候能让元素动起来&#xff0c;当页面滚回顶部的时候&#xff0c;元素能够回到前一个…

关于Java包

我希望我们都同意&#xff0c;方法和类应该很小&#xff0c;并且只有很少的依赖关系。 这种观点被广泛接受&#xff0c;而对“小”的解释则各不相同。 关于这一点有很多文献。 但是包裹呢&#xff1f; 有些人将包视为名称空间。 因此&#xff0c;包只是允许您为类重用名称的东西…

python中打开文件时只允许写入的模式是_详解python中各种文件打开模式

在python中&#xff0c;总的来说有三种大的模式打开文件,分别是:a, w, r当以a模式打开时&#xff0c;只能写文件&#xff0c;而且是在文件末尾添加内容。当以a模式打开时&#xff0c;可以写文件&#xff0c;也可读文件&#xff0c;可是在读文件的时候&#xff0c;会发现读出来的…

KVM 基本硬件容量扩容

在工作当中如果虚拟机的容量不够使用 如何添加呢&#xff1f; CPU添加 cpu添加有两种方式&#xff1a; 1 创建虚拟机的时候可以添加 # virt-install --help | grep cpu--vcpusVCPUS Number of vcpus to configure for your guest. Ex:--vcpus 5--vcpus 5,maxcpus10--vcpu…

JavaFX 2.0 Hello World

在讨论示例本身之前&#xff0c;我想向您展示如何在NetBeans中创建JavaFX应用程序。 &#xff08;如果尚未安装JavaFX和NetBeans&#xff0c;请参阅我以前的文章《 安装JavaFX 2.0和NetBeans 7.7.1》 &#xff09;单击“文件”菜单中的“新建项目”以打开项目向导。 然后选择“…

java 线程强制停止线程_java多线程之停止线程

在多线程开发中停止线程是非常重要的技术点。停止线程在Java语言中并不像break语句那样干脆。须要一些技巧性的处理。一、 异常法採用异常法来停止一个线程。首先我们须要了解一下两个方法的使用方法&#xff1a;1、interrupt()方法public class MyThread extends Thread{Over…

Android 上下文菜单(Context Menu)

一、概述 Android中&#xff0c;上下文菜单是通过onLongClick(...)事件访问的。在事件触发后显示菜单项。 在使用上下文菜单时&#xff0c;通常在onCreate(...)方法中&#xff0c;先行注册上下文菜单。在实现onCreateContextMenu(...)方法和onContextItemSelected(...)方法。 注…