变脸式应用 / 分页列表框架

分页列表框架

本章介绍很常用的分页列表,详情可查阅官方参考文档中的”initPageList”函数介绍。

显示单个列表

当列表预期可能很长时,一般应支持分页。分页列表在手机上的典型展现方式是支持上拉加载和下拉刷新。

[任务]

  • 创建页面orders2,仿照示例应用中订单列表页(orders)。本节先不按订单状态分栏,只显示一个列表,支持上拉加载和下拉刷新。
  • 点击订单列表中的一项,可以进入订单详情页。

我们先熟悉一下支持分页的列表查询接口。
在示例应用自带的模拟数据中,获取订单列表操作是支持分页的,在浏览器控制台上试试调用这些:

callSvrSync("Ordr.query");
// 返回 {nextkey: 20, list: [ {id: 147, dscr: "基础套餐", status: "CR", ...}, ...(共20条)] }

// 取下一页:上次返回的nextkey字段用于本次请求的_pagekey参数
callSvrSync("Ordr.query", {_pagekey: 20}); 
// 返回 {nextkey: 40, list: [ ...(共20条)] }

// 再取下一页
callSvrSync("Ordr.query", {_pagekey: 40}); 
// 返回 {list: [ ...(共8条)] },没有nextkey属性,说明已是最后一页。

默认每次返回20条数据,可以通过_pagesz参数控制每次返回的数据条目数,如:

callSvrSync("Ordr.query", {_pagesz: 10});
// 返回 {nextkey: 10, list: [ ...(共10条)] }

我们使用这个模拟接口,新建页面orders2:

HTML: (page/orders2.html)

<div mui-initfn="initPageOrders2" mui-script="orders2.js">
    <div class="hd">
        <a href="javascript:hd_back();" class="icon icon-back"></a>
        <h2>分页列表练习</h2>
    </div>

    <div class="bd">
        <div id="lst1" data-ac="Ordr.query"></div>
    </div>
</div>

在bd部分中,用一个div(id=lst1)作为列表,用属性”data-ac”指定了后端接口。

在页面初始化函数initPageOrders2中,调用initPageList函数初始化一个分页列表:

JS: (page/orders2.js)

function initPageOrders2()
{
    var jpage = this;
    var listItf = initPageList(jpage, {
        navRef: "",
        listRef: "#lst1",
        onAddItem: onAddItem,
        onNoItem: onNoItem,
    });

    function onAddItem(jlst, itemData)
    {
        var ji = $("<div><b>" + itemData.dscr + "</b><p>订单号: " + itemData.id + "</p></div>");
        ji.appendTo(jlst);

        // 把itemData存储到事件中,可在事件回调中通过ev.data取到数据
        ji.on("click", null, itemData, li_click);
    }

    function onNoItem(jlst)
    {
        var ji = $("<div>没有订单</div>");
        ji.appendTo(jlst);
    }

    function li_click(ev)
    {
        var id = ev.data.id;
        // 显示订单详情页
        PageOrder.id = id;
        MUI.showPage("#order");
    }
}

函数initPageList封装了接口交互的诸多细节,调用者只需要考虑如何展示列表项即可。
在参数中, listRef指定了列表组件的引用(只在当前逻辑页上查找,相当于jpage.find(listRef)),navRef指定导航栏,这里未用到,赋值空就行,后面章节再介绍。
回调函数onAddItem用于添加一个列表项,onNoItem在列表为空时调用,用于显示没有数据时的提示。

我们在首页(page/home.html)中增加一个链接到页面orders2:

<li class="weui_cell" style="display:block"><a href="#orders2" class="weui_btn weui_btn_primary">分页列表练习</a></li>

进入页面,可以看到向下拉动可以刷新列表(重新取第一页数据),快到列表底部时可自动加载下一页数据。

还有个常用的参数是onGetQueryParam,允许编程指定调用后端接口的参数,如:

    var listItf = initPageList(jpage, {
        ...
        // 设置查询参数,静态值一般通过在列表对象上设置属性 data-ac, data-cond以及data-queryParam等属性来指定更方便。
        onGetQueryParam: function (jlst, queryParam) {
            // 指定调用名,参数为固定为"ac"
            queryParam.ac = "Ordr.query";
            // 指定其它后端接口调用参数,比如页大小,查询条件,排序顺序等
            queryParam._pagesz = 10;
            queryParam.orderby = "id desc";
        }
    }

例子中,由于是固定值,也可以在列表上通过属性data-ac="Ordr.query" data-queryParam="orderby:'id desc', _pagesz:10"来指定。

默认页大小是20,由MUI.options.PAGE_SZ定义。

这里有一点要注意:列表的容器(在本例中,#lst1所在容器是.bd)需要有确定的高度,且一般设置样式”overflow-y: auto”,这样列表才能滚动。
由于页面的bd部分刚好会由框架自动设置高度,示例中没有特别去设置,如果是自定义的容器,需要设置好高度。
(TODO:这个限制可能在未来被去掉)

[规约:外界对逻辑页的操作使用逻辑页接口]

上面在显示订单详情页时,用的方法是:

    PageOrder.id = id;
    MUI.showPage("#order");

我们把PageOrder称为逻辑页order的接口(page interface),在H5应用JS文件index.js中定义:

var PageOrder = {
    // PageOrder.id
    id: null, 
};

在页面order的JS逻辑中,会根据这里的PageOrder.id显示相应订单。

尽管也可以通过全局变量等方式实现该功能(例如使用全局变量g_data.orderId),但不够清晰,不建议使用。

外界对逻辑页的操作,都应封装到逻辑页接口中。尤其不要在逻辑页外直接设置该页内的组件。
这样,要查看哪些页面引用了订单页,只要全局查找”PageOrder”即可。

这里要显示订单,也可以这样封装:

var PageOrder = {
    // PageOrder.show(id)
    show: function (id) {
        this.id_ = id;
        MUI.showPage("#order");
    },

    id_: null
};

外面直接这样调用:PageOrder.show(id). 把属性”PageOrder.id”改名为”PageOrder.id_”,暗示这个属性由逻辑页内部用,外界不应使用。

发布了65 篇原创文章 · 获赞 16 · 访问量 8万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章