在新的数据绑定框架中ZK引入了MVVM这种设计模式。关于MVVM的定义可以参考 这里
MVVM作为著名的MVC(Model/View/Controller)模式的一个变种,其主要目的在于将数据与逻辑从表示层中分离出来。也就是所对数据,逻辑和显示的解耦。
MVVM与MVC的基本目标是相同的,而MVVM比MVC更进一步的地方在于对页面控制逻辑和页面本身的解耦。
在传统的MVC框架中,为了改变视图,例如当单价超过1000时输入框显示红色背景,控制器必须持有对视图或视图中元素的引用,例如操作输入框。这样的设计在控制器中对视图有更好的控制,但是却失去了一部分灵活性。
失去的灵活性在于如果对于同一数据和逻辑有一个以上的视图,及多用户感官界面时。控制器对视图的应用所产生的依赖关系,使控制器本身失去了可重用性。
同样是上面的例子,如果同样的输入,对于有些用户提供了一个下拉列表的选择器。显然下拉列表和输入框不是相同的页面组件,其操作方式不同,但是有公用的页面逻辑。
MVVM模式通过ViewModel很好的解决了这一问题。ViewModel可以看做是一个逻辑视图,它包含了所有View的行为和状态,然后通过状态来同步实际的View.这样View可以看做是ViewModel的一个映射,而不同的View只要状态和行为相同便可以映射到相同的ViewModel上来。
在这个模式中最核心也是最巧妙的地方在于, ViewModel中没有持有任何View中可视化元素的引用。
直入主题,下面用一段ZK官方的代码来比较一下两种模式的区别所在,原始页面在 这里
MVC的实现方法(ZK旧的数据绑定方法)
View: helloMVP.zul
<window apply="HelloComposer"> <label id="lbl"/> <button id="btn" label="Show"/> </window>
Controller: HelloComposer.java
public class HelloComposer extends GenericForwardComposer { private Label lbl; public void onClick$btn(Event event) { lbl.setValue("Hello World!"); } }
MVVM的实现方式
View: helloMVVM.zul
<window apply="org.zkoss.bind.BindComposer" viewModel="@bind(vm='org.zkoss.mvvm.examples.hello.HelloViewModel')"> <label value="@bind(vm.message)"/> <button label="Show" onClick="@bind('showHello')"/> </window>
ViewModel: HelloViewModel.java
public HelloViewModel { private String message; public String getMessage() { return message; } @NotifyChange("message") public void showHello() { message = "Hello World!"; } }