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":"奔馳系列","description":"奔馳系列","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,然后是每次懶加載的頁面數據量,這里有個很隱蔽的地方,

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

pages\product\list.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. 不要看上面我只說了很少,這只是核心和思路,具體實現還是要費點心思的。

全文完!


我的其他文章:

       

     只寫原創,敬請關注


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM