微信小程序虛擬列表的應用實例

前言

股票熱門榜單有4000多條,渲染到頁面上在盤中時還得實時更新,如果采用接口和分頁,當下拉幾十頁的時候頁面會變的越來越卡並且還得實時更新,最後的做法是一開始數據就從ws傳遞過來,我們隻需要傳起始下標和結束下標即可,在頁面上我們也隻生成幾個標簽。大大減輕瞭渲染壓力。

什麼是虛擬列表?

就隻指渲染可視區域內的標簽,在滾動的時候不斷切換起始和結束的下標來更新視圖,同時計算偏移。

demo效果

準備工作

  • 計算一屏可展示多少個列表。
  • 盒子的高度。
  • 滾動中起始位置。
  • 滾動中結束位置。
  • 滾動偏移量。

屏高&盒子高度

在小程序中我們可以利用wx.createSelectorQuery來獲取屏高以及盒子的高度。

getEleInfo( ele ) {
    return new Promise( ( resolve, reject ) => {
        const query = wx.createSelectorQuery().in(this);
        query.select( ele ).boundingClientRect();
        query.selectViewport().scrollOffset();
        query.exec( res => {
            resolve( res );
        })
    })
},

this.getEleInfo('.stock').then( res => {
    if (!res[0]) retuen;
    // 屏高
    this.screenHeight = res[1].scrollHeight;
    // 盒子高度
    this.boxhigh = res[0].height;
})

起始&結束&偏移

onPageScroll(e) {
    let { scrollTop } = e;
    this.start = Math.floor(scrollTop / this.boxhigh);
    this.end = this.start + this.visibleCount;
    this.offsetY = this.start * this.boxhigh; 
}

scrollTop可以理解為距離頂部滾過瞭多少個盒子 / 盒子的高度 = 起始下標

起始 + 頁面可視區域能展示多少個盒子 = 結束 

起始 * 盒子高度 = 偏移

computed: {
    visibleData() {
        return this.data.slice(this.start, Math.min(this.end, this.data.length))
    },
}

當start以及end改變的時候我們會使用slice(this.start,this.end)進行數據變更,這樣標簽的內容就行及時進行替換。

優化

快速滾動時底部會出現空白區域是因為數據還沒加載完成,我們可以做渲染三屏來保證滑動時數據加載的比較及時。

prevCount() {
    return Math.min(this.start, this.visibleCount);
},
nextCount() {
    return Math.min(this.visibleCount, this.data.length - this.end);
},
visibleData() {
    let start = this.start - this.prevCount,
        end = this.end + this.nextCount;
    return this.data.slice(start, Math.min(end, this.data.length))
},

如果做瞭前屏預留偏移的計算就要修改下:this.offsetY = this.start * this.boxhigh – this.boxhigh * this.prevCount

滑動動時候start、end、offsetY一直在變更,頻繁調用setData,很有可能導致小程序內存超出閃退,這裡我們在滑動的時候做個節流,稀釋setData執行頻率。

    mounted() {
        this.deliquate = this.throttle(this.changeDeliquate, 130)
    },
    methods: {
        throttle(fn, time) {
            var previous = 0;
            return function(scrollTop) {
                let now = Date.now();
                if ( now - previous > time ) {
                    fn(scrollTop)
                    previous = now;
                }
            }
        },
        changeDeliquate(scrollTop) {
            this.start = Math.floor(scrollTop / this.boxhigh);
            this.end = this.start + this.visibleCount;
            this.offsetY = this.start * this.boxhigh; 
            console.log('執行setData')
        }
    },
    onPageScroll(e) {
	let { scrollTop } = e;
        console.log('滾動================>>>>>>>')
        this.deliquate(scrollTop);
    }

從上圖可以看出,每次滾動差不多都降低瞭setData至少兩次的寫入。

文中編寫的demo在這裡,有需要的可以進行參考。

總結

到此這篇關於微信小程序虛擬列表應用的文章就介紹到這瞭,更多相關小程序虛擬列表內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: