業務需求:
業務需求是給訂單列表添加分頁功能,也就是上拉加載這種每次只請求加載固定數量的數據。
需求分析:
對業務來說就是簡單的分頁上拉加載,但是對於技術實現來說,除了要處理分頁數據的累加加載,還要處理操作訂單返回列表后需要更新列表數據以同步訂單最新狀態,其中的難點在於后者。
當然你可以直接重新初始化列表數據(請求加載第一頁),但是小程序中會記憶數據重載之前的滾動位置,所以要進行處理使頁面滾動到頂部。但是如果訂單列表數據比較多,用戶操作的訂單在第一頁之后,那么操作訂單后返回列表查找之前操作的訂單就比較麻煩了,所以如果要求比較高的話,就不能這么操作了。
比較好的體驗就是用戶操作任何一個訂單,如果訂單狀態改變那么更新列表數據並且返回列表后仍保持在之前操作訂單的位置(只有該訂單狀態改變了,其他都不變)。
實現列表更新訂單位置不變的關鍵代碼:
/** * 將列表數據中指定位置的元素替換為操作訂單所在的那一頁的數據 */ getNewList: function(orderList, curPageList, editPageNum) { if (!orderList || !curPageList || !editPageNum) return; orderList.splice((editPageNum - 1) * this.data.pageSize, this.data.pageSize, ...curPageList) return orderList }
注意:
- 加粗部分為關鍵代碼,其中數組元素替換的索引開始及替換個數根據當前頁碼及每頁顯示個數來定義(這里pageNum從1開始);
- ...curPageList 為es6的擴展運算符,這里的作用是將curPageList的每個元素賦給orderList指定位置的元素進行替換。
整體代碼:
import http from '../../utils/api.js'//接口請求封裝 import coupon from '../../utils/coupon.js'//領取、查看卡券封裝 import util from '../../utils/util.js'//點擊防重等公用方法封裝 Page({ data: { orderList: [], //我的卡券列表 emptyData: '',//接口數據為空標志 pageNum: 1, //頁碼數,默認從1開始 pageSize: 10, //每頁顯示條數,默認10條 ispro: false, //默認不在請求中 isnext: false, //默認有下一頁 }, /** * 生命周期函數--監聽頁面加載 */ onLoad: function(options) { this.getCouponList(1); }, /** * 1.獲取訂單列表 * type 1:初始化加載第一頁 2:觸底加載 參數為空:查看卡券及領取卡券后重新加載數據(頁數不變,替換最后的數據) * editPageNum 領取卡券的訂單所屬的頁數 * 接口調用前根據type進行參數初始化設置 * 接口響應處理中處理是否有下一頁標志及列表數據 */ getCouponList: function(type, editPageNum) { let self = this; let { pageSize, pageNum, orderList } = self.data //觸底加載帶參調用,頁數+1,否則頁數重置為1 if (type == 1) { //頁面初始化加載第一頁 pageNum = 1; orderList = [] } else if (type == 2) { //觸底加載 pageNum++; } else { //領取卡券訂單狀態改變后重載列表指定頁數據 if (editPageNum) pageNum = editPageNum } let params = { openid: wx.getStorageSync("openid"), pageNum: pageNum, pageSize: pageSize } self.setData({ ispro: true }) http.orderList(params).then(data => { let list = data.order_list //接口返回列表數據 if (list.length > 0) { list.map(item => { item.pageNum = pageNum return item }) if (type == 1) { //初始化加載第一頁 orderList = list } else if (type == 2) { //觸底加載,追加數據到列表中 orderList = orderList.concat(list) } else { //查看、領取卡券后只替換數組中當前頁的數據 orderList = self.getNewList(orderList, list, editPageNum) } let hasNextPage = (data.total / pageSize) > pageNum; //是否有下一頁 //給訂單項添加所屬頁數(給訂單狀態改變重載當前頁數據用) self.setData({ orderList: orderList, isnext: hasNextPage, ispro: false, pageNum: pageNum }) } else { self.setData({ ispro: false, emptyData: true }) } }) }, /** * 2.查看訂單 */ viewOrder: function(options) { var self = this let { receive_status, order_no, pagenum } = options.currentTarget.dataset if (!order_no || receive_status == 2) return; if (util.preventDuplicateClicks(4)) return; if (receive_status == 0) { //3. 領取卡券 coupon.couponReceive(order_no, function() { self.getCouponList('', pagenum); }) } else if (receive_status == 1) { //4. 查看卡券 coupon.couponView(order_no) } }, /** * 將列表數據中指定位置的元素替換為操作訂單所在的那一頁的數據 */ getNewList: function(orderList, curPageList, editPageNum) { if (!orderList || !curPageList || !editPageNum) return; orderList.splice((editPageNum - 1) * this.data.pageSize, this.data.pageSize, ...curPageList) return orderList }, /** * 頁面上拉觸底事件的處理函數 */ onReachBottom: function() { var self = this if (!self.data.ispro && self.data.isnext) { self.getCouponList(2) } } })
如上,其中領取卡券會修改訂單狀態,所以重載列表數據放在領取卡券成功后的回調中處理,這樣,用戶完成領取操作返回訂單頁面就已經完成了數據的重載,基本上無感知的。
這里對獲取訂單列表的邏輯進行了全面封裝,集成了頁面初始化數據加載、上拉加載以及領取、查看卡券后列表數據的靜默更新加載。雖然整合起來有點耗腦細胞,不過還好,完美的解決了。
注意事項:
這種方法是基於訂單總條數不變的情況下才可以使用的,一般情況下用戶下單和訂單列表訂單查看是不會同時操作的,也就不會出現查看訂單列表的時候訂單總條數會增加的情況。也只有多端登錄同時操作才有可能發生,這樣的話就需要對列表總條數進行判斷,總條數發生改變的話就需要重新加載第一頁數據並滾動到底部了。