技术开发 频道

ZK5.0客户端与服务器端结合的编程方式

  Server+client混合模式

  除了上面的纯粹的服务器编程方式,我们再介绍一种混合模式。 我们想提高搜索的响应速度,那可以把相应的代码移到客户端。下面我们用搜索功能做一个例子。

  修改现有的代码

  为了在客户端实现搜索功能,首先我们要加载股票数据到客户端,我们使用一个include组件从服务器端加载data.xml。

  Xml代码

<include id="data" src="data.xml" comment="true"/>  

 其次在服务器端的控制器(StockController.java) 可以不要了,它的功能将在客户端实现。

  Xml代码

<borderlayout id="main">  

 另外我们不再在服务器端生成股票列表了,把这部分相关的服务器端代码也除去。

  Xml代码

<listbox id="list" rows="10" width="300px">  

  客户端编程

  为了在客户端实现搜索功能,我们为listbox 创建一个更新方法来生成用户搜索的股票项目。

  Xml代码

<zk xmlns:w="http://www.zkoss.org/2005/zk/client">  
....  
  
<listbox id="list" rows="10" width="300px">  
    
<attribute w:name="update"><![CDATA[
    (function () {
        var data;
        function loadData(w) {
            var xmlDoc = zUtl.parseXML(jq(w).html().replace(/^<!--|-->$/g, '').trim()),
                ids = xmlDoc.getElementsByTagName("id"),
                labels = xmlDoc.getElementsByTagName("name");
            data = [];
            jq(ids).each(function (i) {
                data.push({id: this.firstChild.nodeValue, label: labels[i].firstChild.nodeValue});
            });
        }
        function createItems (listbox, data) {
            if (!data.length) return;
            jq(data).each(function () {
                listbox.appendChild(new zul.sel.Listitem({label: this.label, uuid: this.id}));
            });
        }
        return function (txt) {
            txt = txt || '';
            if (!data) loadData(this.$f('data'));
            this.clear();
            createItems(this, jq.grep(data, function (item) {
                return item.label.toLowerCase().indexOf(txt.toLowerCase()) != -1;
            }));
            this.stripe();
        };
    })()
    
]]></attribute>  
</listbox>  

$f (id), a way to get fellow component. It is the same as getFellow(id), i.e., an alias of getFellow.

http://www.zkoss.org/2005/zk/client is the so-called client namespace that tells ZK engines to generate the code at the client-side instead of server-side.

    然后我们为textbox注册一个客户端的onChange监听方法,这个将方法调用listbox的update方法去更新listbox。注意我们要声明一个命名空间(w: ),因为这个监听器是在客户端的。

  Xml代码

<textbox id="inp" w:onChanging="this.$f('list').update(event.data.value)"/>  

  此外,我们还要在一开始显示所有的股票,这需要调用注册一个bind_方法来实现初始化,这个方法将调用listbox的update方法。

  Xml代码

<listbox id="list" rows="10" width="300px">  
    
<attribute w:name="bind_">  
    function (desktop, skipper, after) {  
        this.$bind_.apply(this, arguments);  
        var self = this;  
        after.push(function () {  
            self.update();  
            self.firstChild.setSelected(true);  
        });  
    }  
    
</attribute>  
....  
</listbox>  

        和服务器端交互

  最后,还需要和服务器端交换,用户点击一支股票,需要告诉服务器更新历史价格的表格和图表。在listbox上指定onSelect事件,这样一旦用户点击了一个股票,ZK引擎将给服务器发送一个onSelect事件。

  Xml代码

<listbox id="list" onSelect="" rows="10" width="300px">

  接下来,为了在服务器端处理onSelect事件, 我们在服务器端实现一个service,通过它我们可以实现股票历史价格的更新:

  Xml代码

<listbox id="list" onSelect="" rows="10" width="300px">  
....  
</listbox>  
<include id="content" src="price.zul?id=1"/>  
<zscript>  
    public class MyService implements org.zkoss.zk.au.AuService {  
        public boolean service(org.zkoss.zk.au.AuRequest request, boolean everError) {  
            final String cmd = request.getCommand();  
            if (cmd.equals(Events.ON_SELECT)) {  
                String uuid = ((List)request.getData().get("items")).get(0);  
                System.out.println("selected:" + uuid);  
                content.setSrc("price.zul?id=" + uuid);  
                return true;  
            }  
            return false;  
        }  
    }  
    list.setAuService(new MyService());  
</zscript>  

    总结

  在上文中,我们演示了两种不同的实现方式——纯粹的服务器编程和客户端/服务器混合编程——来实现同一个应用。无论使用哪一种,ZK 5 提供了一种新的方式来平衡易于开发和更多的可控性。

  译注:最后上传两张IDE中的截图吧,我用的是ZK3.6.2,客户端/服务器端混合编程的方式没有去做。

0
相关文章