H5開發移動應用APP(店鋪系列一)

首先,這是個真實的案例,我大兄弟在深圳開汽修店鋪,但需要系統來管理日常經營活動,這正不是我擅長的嗎?

說干就干,直接後端+web端+移動端來一套,於是緊急趕工,起早摸黑,產出約3萬行總量程式碼,此系統與工作無關,

純屬個人業餘開發,所以我敢拿來任意剖析,如果有時間我就出個連載,做一些典型的技術解析。這次說下移動端開發,

考慮到適配和多端問題,還有效率原因,我選擇了混合模式,即原生做殼,H5+CSS做內容展現,JS程式碼實現邏輯,

然後用第三方工具打包生成移動App,我們來看下懶載入模式。

 

準備:

Idea2019.03/Gradle6.0.1/JDK11.0.4/Lombok0.28/SpringBoot2.2.4RELEASE/mybatisPlus3.3.0/Soul2.1.2/Dubbo2.7.5

/Mysql8.0.11/Vue2.5/OSS/Hbuilder2.6.1

 

難度: 新手--戰士--老兵--大師

目標:

1.前端展現數據懶載入實現

步驟:

為了遇見各種問題,同時保持時效性,我盡量使用最新的軟體版本。程式碼地址:https://github.com/xiexiaobiao/vehicle-shop-mobile.git

1 本套系統大體情況

後端程式碼量約1.5萬,雙前端約1.5萬,技術還是很具代表性的,不然就不好意思拿出來說事了,詳細可看Git庫說明,下圖是後端程式碼量分析:

 

 

 

Web管理介面:

 

 

 

手機端:使用Hbuilder編碼,Uniapp框架,再隨手撿了幾個UI拿來大改了幾下,基本形狀如下:

 

 

 

 

 

 

2 數據懶載入

比如上圖中商品頁和訂單列表頁,數據流量還是很大的,因為裡面參雜了圖片,如果一上來就一股腦全載入,再搞個前端快取假分頁載入,那你得考慮下用戶的

感受!以此需要懶載入,或者叫漸進式載入,必須得結合後端物理分頁實現。

思路:後端物理分頁,前端首次進頁面,先請求一次後端並載入到頁面,後續操作中頁面滑到底後自動觸發後續載入並請求後端,將返回數據累加到前端快取數組,

再載入到頁面,直到數據全部完畢。

首先定義後端(有點不規範,把數據處理寫在controller層,沒來得及優化):

com.biao.shop.stock.controller.ShopItemController:

@GetMapping("/item/list")      public ObjectResponse<Page<ShopItemEntityDto>> listItem(@RequestParam("pageNum") int current, @RequestParam("pageSize")int size,                                                  @RequestParam(value = "itemName",required = false) String itemName,                                                  @RequestParam(value = "itemUuid",required = false)String itemUuid,                                                  @RequestParam(value = "category",required = false) String category,                                                  @RequestParam(value = "brandName",required = false)String brandName,                                                  @RequestParam(value = "shipment",required = false) Integer shipment){          int shipmentTemp = Objects.isNull(shipment)? 2: shipment;          // 這裡的shipment最好設計為int,可以接收 0 1 2 ,boolean型,只能是0 1,前端傳來都會自帶默認0,導致無法查詢無此條件限制的          Page<ShopItemEntityDto> pageInfo = shopItemService.listItem(current,size,itemName,itemUuid,category,brandName,shipmentTemp);          ObjectResponse<Page<ShopItemEntityDto>> response = new ObjectResponse<>();              response.setCode(RespStatusEnum.SUCCESS.getCode());              response.setMessage(RespStatusEnum.SUCCESS.getMessage());              response.setData(pageInfo);          return response;      }

以上程式碼是controller層,具體後端服務實現我就省略了,請看Git源碼,返回給web端是個簡單的統一返回封裝,

ObjectResponse{"code":200,"message":"SUCCESS","data":{Object}},其數據就是Page類型,具體是MybatisPlus中的

com.baomidou.mybatisplus.core.metadata.Ipage, 包含了數據總量,當前頁數和每頁的量,來個例子就是下面這樣的:

{"code":200,"message":"SUCCESS","data":{"records":[{"idItem":2,"itemUuid":"SP000011","category":"修理","classification":null,"itemName":"雨刮器","sellPrice":60.99,"purchasePrice":45.99,"brandName":"Benz系列","description":"Benz系列","shipment":null,"alertQuantity":5,"specification":"35*35cm","unit":"支","picAddr":"https://biao-aliyun-oss-pic-bucket.oss-cn-shenzhen.aliyuncs.com/images/logo-samll.png","stock":null,"sales":null,"discountPrice":null}],"total":23,"size":500,"current":1,"orders":[],"searchCount":true,"pages":1}

 

那前端就是先定義一個初始請求的量,初始頁值必須為 1,然後是每次懶載入的頁面數據量,這裡有個很隱蔽的地方,

必須保證首次懶載入的頁面數據量填滿螢幕,否則無法觸發螢幕觸底上滑載入:

pagesproductlist.vue文件

data() {      return {          // 分頁實現頁面懶載入          pageInfo:{              "total": 0,              "size": 6,  // 每次懶載入的頁面數據量              "current":1//    首次請求的初始頁值,之後每請求一次就累加 1                  },  ...  }

 

 每次請求數據的方法封裝一下:

requesForData:function(){      Request().request({          url:'stock/vehicle/stock/item/list',          method: 'get',          header:{},          params: {              'pageNum': this.pageInfo.current,              'pageSize': this.pageInfo.size,          },          }      ).then(          res => {              let pdtArr = res.data.records;              this.goodsList = this.goodsList.concat(pdtArr);              // 懶載入機制 --> 載入一次後累加頁數              this.pageInfo.total = res.data.total;              this.pageInfo.current  += 1;                      }                  ).catch(err => {                      console.error('is catch', err)                      this.err = err;      });

以上程式碼中,要實現懶載入機制,需每次載入一次後累加當前頁數,另外使用Array.concat函數,追加到已有的數組後面,這樣懶載入基本就成型了!

3 如何觸發每次的懶載入?

方法一:uniapp頁面有個自帶的鉤子:

//載入更多  onReachBottom(){      console.log("onReachBottom")      this.loadData();  },

 

方法二:頁面模板中的scroll-view元素,加上@scrolltolower事件函數:

<scroll-view      class="list-scroll-content"      scroll-y      @scrolltolower="loadData"      :refresher-enabled = "false"  >

同時配合:

<uni-load-more :status="tabItem.loadingType"></uni-load-more>

 

當然,必須有個指示器,告知數據是否全部完畢了, 在loadData方法中最後加一個判斷:

//判斷是否還有數據, 有改為 more, 沒有改為noMore  if(this.pageInfo.total > (this.pageInfo.current-1) * this.pageInfo.size){      navItem.loadingType = 'more';  }elseif(this.pageInfo.total <= (this.pageInfo.current-1) * this.pageInfo.size){      navItem.loadingType = 'noMore';  }

收工結束!

後記:

  1. 懶載入必須配合後端的物理分頁機制實現,
  2. 避免數據前端過濾後導致頁面數據沒法到達螢幕底部,結果全部數據完畢還沒完,但已有的數據卻不滿一屏,這就不能自動觸發事件了!所以,必須禁止懶載入模式下前端數據過濾,即帶條件後端查數據,
  3. 數據載入,要注意與頁面渲染的前後順序,不然頁面元素都渲染完了,你數據還沒來就尷尬了,上面的後端數據請求可以看到,現在axios都是非同步的,返回Promise對象,目前最新的解決辦法就是可以使用 async / await 來保證非同步程式碼的執行順序,但是一定注意 await 後必須是返回Promise對象,否則不保證程式碼順序!如果出現頁面載入完了,數據還沒出來,可以多寫幾個console.log(),看是否頁面渲染在前,數據返回在後。
  4. 不要看上面我只說了很少,這只是核心和思路,具體實現還是要費點心思的。

全文完!


我的其他文章:

       

     只寫原創,敬請關注

Tags: