zk官方MVC原理详解(二)

在某些情况下,因为某些原因我们可能从其他的类中继承了我们的Composer,我们是不是不能使用像GenericXxxComposer一些特性呢?并不是的,zk团队提供了三个对应核心辅助方法无需继承GenericXxxComposer也能实现相同的功能

(在Qamaralzaman Habeek写一篇文章中也提到这种方式来自动注册监听zk事件)

composer6.zul

<window title="composer6 example" border="normal" width="300px" apply="MyComposer6">
    <grid>
        <rows>
            <row>First Name: <textbox id="firstName"/></row>
            <row>Last Name: <textbox id="lastName"/></row>
            <row>Full Name: <label id="fullName"/></row>
        </rows>
    </grid>
</window>
MyComposer6.java

public class MyComposer6 implements Composer {
    private Textbox firstName;
    private Textbox lastName;
    private Label fullName;
    
    public void doAfterCompose(Component win) throws Exception {
         //wire variables
        Components.wireVariables(win, this);

        //register onXxx event listeners
        Events.addEventListeners(win, this);
        
        //auto forward 
        Components.addForwards(win, this);
    }
    
    public void onChange$firstName(Event event) { 
        fullName.setValue(firstName.getValue()+" "+lastName.getValue());
    }
    
    public void onChange$lastName(Event event) {
        fullName.setValue(firstName.getValue()+" "+lastName.getValue());
    }
}

Composer6 例子是重写Composer1例子. 请看下面几个方法定义.

  • org.zkoss.zk.ui.event.Events.addEventListeners(Component comp, Object controller): Add onXxx event listener defined in controller object to the specified component. This helper method registers those onXxx events to the specified component so you don't have to implement and add EventListener into the component one by one. This helper method provides the same feature of the GenericComposer. (在控制器对象为指定的组件新增定义onXxx事件监听器,此辅助方法注册的onXxx事件到指定的组件,所以你不需要一个一个实现且添加EventListener,在GenericComposer也提供相同的特性功能 )
  • org.zkoss.zk.ui.Components.wireVariables(Component comp, Object controller): Wire accessible variable objects of the specified component into a controller Java object. This helper method wire the embedded objects, components, and accessible variables into the controller object per the components' id and variables' name automatically for you so you don't have to call getFellows() or Path.getComponents() etc. to get references. This helper method provides the same feature of the GenericAutowireComposer.                (wire指定组件访问对象变量到java对象控制器,这个辅助方法wire内嵌对象,组件和访问变量到控制器对象,使每个组件ID和变量名自动的绑定,这样就不需要调用getFellows()或者Path.getComponent.等等来获取引用。在GenericAutowireComposer也提供相同特性功能
  • org.zkoss.zk.ui.Components.addForwards(Component comp, Object controller): Adds forward conditions to the source components defined in the controller object so their onXxx events can be forwarded to the specified target component. This helper method searchs those onXxx$id methods defined in the controller object and adds forward condition to the components as specified in id so you don't have to specify in zul file the forward attribute one by one. This helper mehtod provides the same feature of the GenericForwardComposer. (给定义在控制器对象中组件添加forward条件,其onXxx事件组件可以被转发到指定的目标组件,这个辅助类将会在控制器对象中搜索onxxx$id方法并且根据指定id来添加forword条件,所以你不需要在zul文件中一一的去指定forward。在GenericForwardComposer也提供了相同的特性功能

一开始,ZK已经提供了一种通过使用自定义的组件作为控制器的MVC。

"我们能否在这种条件下(自定义组件为控制器的MVC)使用这三个辅助方法呢?" 当然了可以了!

mywindow.zul
<window title="mywindow example" border="normal" width="300px" use="MyWindow">
    <grid>
        <rows>
            <row>First Name: <textbox id="firstName"/></row>
            <row>Last Name: <textbox id="lastName"/></row>
            <row>Full Name: <label id="fullName"/></row>
        </rows>
    </grid>
</window>
MyWindow.java

...
public class MyWindow extends Window implements AfterCompose {
    private Textbox firstName;
    private Textbox lastName;
    private Label fullName;

    //-- AfterCompose --//
    public void afterCompose() {
        //wire variables
        Components.wireVariables(this, this);
        
        //NO need to register onXxx event listeners

        //auto forward
        Components.addForwards(this, this);
    }
    public void onChange$firstName(Event event) { 
        fullName.setValue(firstName.getValue()+" "+lastName.getValue());
    }
    
    public void onChange$lastName(Event event) {
        fullName.setValue(firstName.getValue()+" "+lastName.getValue());
    }
}

正如你说看到的一样,mywindow的实际上类似于MyComposer6. 不同的是这里使用了use属性, 组件和控制器是一个对象. 我们需要在MyWindow calss中找到合适的时机来调用auto-wire和add-forword辅助方法。在这个例子中, 我选择实现 org.zkoss.zk.ui.ext.AfterCompose 接口 并且在接口afterCompose方法中调用auto-wire 和add-forward 辅助方法 .当所有的子组件渲染完成时候zk装载引擎将会调用afterCompose()就像composer中的doaftercompose方法一样 。注意,在这里我们不需要明确地注册onxxx事件监听。ZK的更新引擎将会自动调用定义在组件中onXxx事件监听。

Download the example codes(.war file).

zk编程所有都是关于事件处理和用户界面组件操纵。显然, 在业务逻辑中到处都是事件监听器,他操纵这代码并且协调一切. 使得MVC编程更容易, 我们已经可以更容易写出代码控制层. 因此,下面就是我们已经实现的目标:

  • Make writing event listener easier.
  • Make register event listener easier.
  • Make accessing UI components and data beans easier.

可以使用隐式对象auto-wiring, 可以像复制和粘贴代码从快速原型zscript重构出来

我们希望你喜欢这些ZK的新功能和使用ZK愉快的写你的MVC代码。如果你提出任何想法,请随时反馈,我们可以使ZK的编程更容易,更好,更强大。

原文地址:https://www.cnblogs.com/xiaopen/p/zk_mvc2.html