wepy小程式長列表效能優化實踐
背景
- wepy 1.7.3
- wepy-redux
長列表互動問題
wepy
框架的列表性效能比較差,主要原因是修改列表中任意欄位的時候,會給setData
傳遞完整的列表,詳細見這個issue
;
此時修改長列表任意欄位,都會導致頁面長時間不響應
解決
使用字典(Object
)與長列表進行組合,因為一般情況下字典的資料量會遠遠小於列表
場景
任意彈窗對購物車cart
進行修改,產品列表對應的購買數量同步修改
// 資料結構 // 產品列表(長度3000+) var products = [{id: "79", name: "精緻葷菜"}...] // 購物車字典 // key: productId, value: 購物車資料 var cartDict = { 2407: { price: "1.02" num: 2 } }
注意由於cartDict
資料為使用者手動新增,資料量遠遠小於列表。那麼setData
時速度也會相應提高
此時我們使用組合
方式渲染列表的購買量
<view class="num" wx:if="{{ cartDict[product.id] }}">{{cartDict[product.id].num}}</view>
通過將每次修改列表轉移為每次修改cartDict來達到提升效能的效果;上面那個issue
也可以用類似思路製作一個展開產品的字典
首次載入白屏問題
我們的商品列表一般會比較長(目前最大有3000+個),此時第一次進入頁面白屏時間很長(10s+);
解決
使用h5的優化思路,類似app。只渲染一部分螢幕內的產品,其他絕大部分產品使用骨架
展示;使用此方法有一些限制
- 產品高度需要已知,用來計算當前產品是否在螢幕內
- 滾動體驗沒有不優化的好,小程式其實也是用的這種列表優化思路,因此快速滾動的時候實際效果是
白屏
(小程式優化) =>骨架
(我們的優化)
=> 出現產品
場景
我們專案所有產品等高,因此比較好計算當前產品是否應該展示。
首先是模板寫法
<repeat for="{{products}}" item="dish" index="index"> <dishItem :dish="dish" wx:if="{{showTypeDict[type.id]}}"></dishItem> <view wx:else> <image src="{{_skeleton}}"></image> </view> </repeat>
說明:
-
showTypeDict
代表當前需要展示的產品字典,使用字典原因是基於長列表互動問題
- 對產品進行分類,每次只比較分類的座標然後展示整個分類
- dishItem是產品對應元件,比較複雜
- skeleton為骨架
監聽scroll,根據當前scrollTop和產品分類的座標來決定showTypeDict
的內容,注意截流;
使用以上方法優化後3000+產品白屏時間與100+產品持平。滾動時無卡頓,快速滾動時需要等待一會兒產品才能渲染出來;
以上