新聞中心
recycle-view
小程序長列表組件

使用此組件需要依賴小程序基礎(chǔ)庫 2.2.2 版本,同時依賴開發(fā)者工具的 npm 構(gòu)建。具體詳情可查閱官方 npm 文檔。
背景
?目前小程序會有不少的應(yīng)用場景里會用到無限長列表的交互,當(dāng)一個頁面展示很多信息的時候,會造成小程序頁面的卡頓以及白屏。原因有如下幾點:
- 列表數(shù)據(jù)很大,首次 setData 的時候耗時高
- 渲染出來的列表 DOM 結(jié)構(gòu)多,每次 setData 都需要創(chuàng)建新的虛擬樹、和舊樹 diff 操作耗時都比較高
- 渲染出來的列表 DOM 結(jié)構(gòu)多,占用的內(nèi)存高,造成頁面被系統(tǒng)回收的概率變大。
因此就有長列表組件來解決這些問題。
實現(xiàn)思路
?核心的思路是只渲染顯示在屏幕的數(shù)據(jù),基本實現(xiàn)就是監(jiān)聽 scroll 事件,并且重新計算需要渲染的數(shù)據(jù),不需要渲染的數(shù)據(jù)留一個空的 div 占位元素。
假設(shè)列表數(shù)據(jù)有100個 item,知道了滾動的位置,怎么知道哪些 item 必須顯示在頁面?因為 item 還沒渲染出來,不能通過 getComputedStyle 等 DOM 操作得到每個 item 的位置,所以無法知道哪些 item 需要渲染。為了解決這個問題,需要每個 item 固定寬高。item 的寬高的定義見下面的 API 的createRecycleContext()的參數(shù) itemSize 的介紹。
滾動過程中,重新渲染數(shù)據(jù)的同時,需要設(shè)置當(dāng)前數(shù)據(jù)的前后的 div 占位元素高度,同時是指在同一個渲染周期內(nèi)。頁面渲染是通過 setData 觸發(fā)的,列表數(shù)據(jù)和 div 占位高度在2個組件內(nèi)進行 setData 的,為了把這2個 setData 放在同一個渲染周期,用了一個 hack 方法,所以定義 recycle-view 的 batch 屬性固定為 batch="{{batchSetRecycleData}}"。
在滾動過程中,為了避免頻繁出現(xiàn)白屏,會多渲染當(dāng)前屏幕的前后2個屏幕的內(nèi)容。
包結(jié)構(gòu)
長列表組件由2個自定義組件 recycle-view、recycle-item 和一組 API 組成,對應(yīng)的代碼結(jié)構(gòu)如下
├── miniprogram-recycle-view/
└── recycle-view 組件
└── recycle-item 組件
└── index.js
包結(jié)構(gòu)詳細描述如下:
| 目錄/文件 | 描述 |
|---|---|
| recycle-view 組件 | 長列表組件 |
| recycle-item 組件 | 長列表每一項 item 組件 |
| index.js | 提供操作長列表數(shù)據(jù)的API |
使用方法:
1.安裝組件
npm install --save miniprogram-recycle-view2.在頁面的 json 配置文件中添加 recycle-view 和 recycle-item 自定義組件的配置
{
"usingComponents": {
"recycle-view": "miniprogram-recycle-view/recycle-view",
"recycle-item": "miniprogram-recycle-view/recycle-item"
}
}3.WXML 文件中引用 recycle-view
長列表前面的內(nèi)容
{{item.idx+1}}. {{item.title}}
長列表后面的內(nèi)容
recycle-view 的屬性介紹如下:
| 字段名 | 類型 | 必填 | 描述 |
|---|---|---|---|
| id | String | 是 | id必須是頁面唯一的字符串 |
| batch | Boolean | 是 | 必須設(shè)置為{{batchSetRecycleData}}才能生效 |
| height | Number | 否 | 設(shè)置recycle-view的高度,默認為頁面高度 |
| width | Number | 否 | 設(shè)置recycle-view的寬度,默認是頁面的寬度 |
| enable-back-to-top | Boolean | 否 | 默認為false,同scroll-view同名字段 |
| scroll-top | Number | 否 | 默認為false,同scroll-view同名字段 |
| scroll-y | Number | 否 | 默認為true,同scroll-view同名字段 |
| scroll-to-index | Number | 否 | 設(shè)置滾動到長列表的項 |
| placeholder-image | String | 否 | 默認占位背景圖片,在渲染不及時的時候顯示,不建議使用大圖作為占位。建議傳入SVG的Base64格式,可使用工具將SVG代碼轉(zhuǎn)為Base64格式。支持SVG中設(shè)置rpx。 |
| scroll-with-animation | Boolean | 否 | 默認為false,同scroll-view的同名字段 |
| lower-threshold | Number | 否 | 默認為false,同scroll-view同名字段 |
| upper-threshold | Number | 否 | 默認為false,同scroll-view同名字段 |
| bindscroll | 事件 | 否 | 同scroll-view同名字段 |
| bindscrolltolower | 事件 | 否 | 同scroll-view同名字段 |
| bindscrolltoupper | 事件 | 否 | 同scroll-view同名字段 |
recycle-view 包含3個 slot,具體介紹如下:
| 名稱 | 描述 |
|---|---|
| before | 默認 slot 的前面的非回收區(qū)域 |
| 默認 slot | 長列表的列表展示區(qū)域,recycle-item 必須定義在默認 slot 中 |
| after | 默認 slot 的后面的非回收區(qū)域 |
長列表的內(nèi)容實際是在一個 scroll-view 滾動區(qū)域里面的,當(dāng)長列表里面的內(nèi)容,不止是單獨的一個列表的時候,例如我們頁面底部都會有一個 copyright 的聲明,我們就可以把這部分的內(nèi)容放在 before 和 after 這2個 slot 里面。
recycle-item 的介紹如下:
需要注意的是,recycle-item 中必須定義 wx:for 列表循環(huán),不應(yīng)該通過 setData 來設(shè)置 wx:for 綁定的變量,而是通過createRecycleContext方法創(chuàng)建RecycleContext對象來管理數(shù)據(jù),createRecycleContext在 index.js 文件里面定義。建議同時設(shè)置 wx:key,以提升列表的渲染性能。
4.頁面 JS 管理 recycle-view 的數(shù)據(jù)
const createRecycleContext = require('miniprogram-recycle-view')
Page({
onReady: function() {
var ctx = createRecycleContext({
id: 'recycleId',
dataKey: 'recycleList',
page: this,
itemSize: { // 這個參數(shù)也可以直接傳下面定義的this.itemSizeFunc函數(shù)
width: 162,
height: 182
}
})
ctx.append(newList)
// ctx.update(beginIndex, list)
// ctx.destroy()
},
itemSizeFunc: function (item, idx) {
return {
width: 162,
height: 182
}
}
})頁面必須通過 Component 構(gòu)造器定義,頁面引入了miniprogram-recycle-view包之后,會在 wx 對象下面新增接口createRecycleContext函數(shù)創(chuàng)建RecycleContext對象來管理 recycle-view 定義的的數(shù)據(jù),createRecycleContext接收類型為1個 Object 的參數(shù),Object 參數(shù)的每一個 key 的介紹如下:
| 參數(shù)名 | 類型 | 描述 |
|---|---|---|
| id | String | 對應(yīng) recycle-view 的 id 屬性的值 |
| dataKey | String | 對應(yīng) recycle-item 的 wx:for 屬性設(shè)置的綁定變量名 |
| page | Page/Component | recycle-view 所在的頁面或者組件的實例,頁面或者組件內(nèi)可以直接傳 this |
| itemSize | Object/Function | 此參數(shù)用來生成recycle-item的寬和高,前面提到過,要知道當(dāng)前需要渲染哪些item,必須知道item的寬高才能進行計算 Object必須包含{width, height}兩個屬性,F(xiàn)unction的話接收item, index這2個參數(shù),返回一個包含{width, height}的Object itemSize如果是函數(shù),函數(shù)里面 this指向RecycleContext如果樣式使用了rpx,可以通過transformRpx來轉(zhuǎn)化為px。 為Object類型的時候,還有另外一種用法,詳細情況見下面的itemSize章節(jié)的介紹。 |
| useInPage | Boolean | 是否整個頁面只有recycle-view。Page的定義里面必須至少加空的onPageScroll函數(shù),主要是用在頁面級別的長列表,并且需要用到onPullDownRefresh的效果。切必須設(shè)置root參數(shù)為當(dāng)前頁面對象 |
| root | Page | 當(dāng)前頁面對象,可以通過getCurrentPages獲取, 當(dāng)useInPage為true必須提供 |
RecycleContext 對象提供的方法有:
| 方法 | 參數(shù) | 說明 |
|---|---|---|
| append | list, callback | 在當(dāng)前的長列表數(shù)據(jù)上追加list數(shù)據(jù),callback是渲染完成的回調(diào)函數(shù) |
| splice | begin, count, list, callback | 插入/刪除長列表數(shù)據(jù),參數(shù)同Array的splice函數(shù),callback是渲染完成的回調(diào)函數(shù) |
| update | begin, list, callback | 更新長列表的數(shù)據(jù),從索引參數(shù)begin開始,更新為參數(shù)list,參數(shù)callback同splice。 |
| destroy | 無 | 銷毀RecycleContext對象,在recycle-view銷毀的時候調(diào)用此方法 |
| forceUpdate | callback, reinitSlot | 重新渲染recycle-view。callback是渲染完成的回調(diào)函數(shù),當(dāng)before和after這2個slot的高度發(fā)生變化時候調(diào)用此函數(shù),reinitSlot設(shè)置為true。當(dāng)item的寬高發(fā)生變化的時候也需要調(diào)用此方法。 |
| getBoundingClientRect | index | 獲取某個數(shù)據(jù)項的在長列表中的位置,返回{left, top, width, height}的Object。 |
| getScrollTop | 無 | 獲取長列表的當(dāng)前的滾動位置。 |
| transformRpx | rpx | 將rpx轉(zhuǎn)化為px,返回轉(zhuǎn)化后的px整數(shù)。itemSize返回的寬高單位是px,可以在這里調(diào)用此函數(shù)將rpx轉(zhuǎn)化為px,參數(shù)是Number,例如ctx.transformRpx(140),返回70。注意,transformRpx會進行四舍五入,所以transformRpx(20) + transformRpx(90)不一定等于transformRpx(110) |
| getViewportItems | inViewportPx | 獲取在視窗內(nèi)的數(shù)據(jù)項,用于判斷某個項是否出現(xiàn)在視窗內(nèi)。用于曝光數(shù)據(jù)上報,菜品和類別的聯(lián)動效果實現(xiàn)。參數(shù)inViewportPx表示距離屏幕多少像素為出現(xiàn)在屏幕內(nèi),可以為負值。 |
其中 itemSize 的使用
itemSize可以為包含{width, height}的Object,所有數(shù)據(jù)只有一種寬高信息。如果有多種,則可以提供一個函數(shù),長列表組件會調(diào)用這個函數(shù)生成每條數(shù)據(jù)的寬高信息,如下所示:
function(item, index) {
return {
width: 195,
height: item.azFirst ? 130 : 120
}
}提示:
- recycle-view設(shè)置batch屬性的值必須為{{batchSetRecycleData}}。
- recycle-item的寬高必須和itemSize設(shè)置的寬高一致,否則會出現(xiàn)跳動的bug。
- recycle-view設(shè)置的高度必須和其style里面設(shè)置的樣式一致。
- createRecycleContext(options)的id參數(shù)必須和recycle-view的id屬性一致,dataKey參數(shù)必須和recycle-item的wx:for綁定的變量名一致。
- 不能在recycle-item里面使用wx:for的index變量作為索引值的,請使用{{item._index_}}替代。
- 不要通過setData設(shè)置recycle-item的wx:for的變量值,建議recycle-item設(shè)置wx:key屬性。
- 如果長列表里面包含圖片,必須保證圖片資源是有HTTP緩存的,否則在滾動過程中會發(fā)起很多的圖片請求。
- 有些數(shù)據(jù)不一定會渲染出來,使用wx.createSelectorQuery的時候有可能會失效,可使用RecycleContext的getBoundingClientRect來替代。
- 當(dāng)使用了useInPage參數(shù)的時候,必須在Page里面定義onPageScroll事件。
- transformRpx會進行四舍五入,所以transformRpx(20) + transformRpx(90)不一定等于transformRpx(110)
- 如果一個頁面有多個長列表,必須多設(shè)置batch-key屬性,每個的batch-key的值和batch屬性的變量必須不一致。例如
分享標題:創(chuàng)新互聯(lián)小程序教程:微信小程序 擴展組件·小程序長列表組件
URL鏈接:http://www.5511xx.com/article/dpcpjhi.html


咨詢
建站咨詢
