分頁列表框架

天笑發表於2017-02-16

本章介紹很常用的分頁列表,詳情可查閱官方參考文件中的"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_",暗示這個屬性由邏輯頁內部用,外界不應使用。

相關文章