虛擬列表(VirtualList)在Taro3中的使用


技術概述

虛擬列表(VirtualList)是一種在展示大量數據(長列表)時使用的插件,通過只顯示必要的DOM和無限滾動,提升頁面的性能。在web環境中,我們可以使用vue-virtual-scroll-list之類的npm包。最近熱門的小程序框架Taro3也提供了這個能力。從文檔說明上看,其功能算是vue-virtual-scroll-list的一個子集。

技術詳述

在Taro中使用VirtualList非常簡單,我們以Vue.js模式的項目為例——

這里是一個單詞列表頁面,需要展示數千個單詞及中文,如果直接展示,頁面的將會卡頓較長時間(團隊成員也提出了這一點見issue),因此經過考慮我們選用了VirtualList作為解決方案,幾乎不再會卡頓。以下是精簡后的代碼。
完整代碼點此:Zhai-dict

1. 引入必要文件

// app.js 入口文件
import VirtualList from `@tarojs/components/virtual-list`

Vue.use(VirtualList)

2. 編寫單項組件,用於長列表單個項目的展示

<! –– ListItem.vue 單項組件 ––> 
<template>
  <!-- 這里的style=css是一定要加的 -->
  <view class="word-wrapper" :style="css">
    <view class="word">{{ data[index].word }}</view>
    <view class="translation">{{ data[index].translation }}</view>
  </view>
</template>

<script>
export default {
  name: 'ListItem',
  props: ['index', 'data', 'css']
}
</script>

<style lang="scss">
.word-wrapper {
  position: relative;
  box-sizing: border-box;
  width: 100%;
  padding: 30px 20px;
  background: #f7f7f7;
  border-bottom: 1px solid #dddddd;
...
}

傳入該組件的props有以下4個屬性:

  • css: 單項的樣式,樣式必須傳入組件的 style 中
  • data: 組件渲染的數據,即virtualList的itemData屬性
  • index: 組件渲染數據的索引
  • isScrolling: 組件是否正在滾動,當 useIsScrolling 值為 true 時返回布爾值,否則返回 undefined

通過這些屬性可以渲染出單個的組件。

3. 編寫長列表頁面組件

<! –– History.vue 頁面組件 ––> 
<template>
  <view id="pHistory">
    <virtual-list
      :height="listHeight"
      :item-data="wordList"
      :item-count="wordList.length"
      :item-size="75"
      :item="ListItem"
      width="100%"
      v-if="wordList.length"
      :overscanCount="20"
    />
    <view class="empty" v-show="wordList.length === 0">- 暫無內容 -</view>
  </view>
</template>

<script>
import Taro from '@tarojs/taro'
import ListItem from './components/ListItem.vue'

export default {
  name: 'pageHistory',
  data() {
    return {
      pageState: 1,
      wordList: [],
      ListItem
    }
  },
  computed: {
    listHeight() {
      return Taro.getSystemInfoSync().windowHeight - 50
    }
  },
}
</script>

virtualList的常用屬性如下:

  • item: VueComponent
    將要渲染的列表單項組件,傳入的props如上文所述。
  • itemCount: number
    列表的長度。必填。
  • itemData: Array
    渲染數據。必填。
  • itemSize: number
    列表單項的大小,垂直滾動時為高度,水平滾動時為寬度。必填。
  • height: number | string
    列表的高度。當滾動方向為垂直時必填。
  • width: number | string
    列表的寬度。當滾動方向為水平時必填。
  • overscanCount: number = 1
    在可視區域之外渲染的列表單項數量,值設置得越高,快速滾動時出現白屏的概率就越小,相應地,每次滾動的性能會變得越差。

注意事項&最佳實踐

  1. 單項組件中,根元素一定要加上:style="css",哪怕你沒有傳入自定義的css。沒有加上會導致滾動之后頁面顯示不完全。
  2. height屬性一定要是一個固定值,不能是百分比或vh/vw等。可以在computed里面進行一系列處理,如History.vue32行。
  3. 由於小程序的性能稍差,建議overscanCount設一個稍大的值,可能會有較好的展示效果。當然,過大的值也會產生反效果,這需要開發者進行一定嘗試。

總結

本例的數據是從本地讀取,因此也無需使用“無限滾動”的方案。虛擬列表組件和分頁都是大量數據場景下提升性能的有效解決方案,在實際使用中有較大的意義。
從原理來看,這些組件都是通過計算好列表的長度,在wrapper處加上合適的padding-top和padding-bottom撐起這個列表,同時通過IntersectionObserver等方式判斷組件是否進入/離開了視口,並且只保留距離視口一定范圍內的DOM元素。隨着用戶滾動不斷更新展示的組件,這樣就在用戶無感的情況下做到了對超長列表的部分展示。

參考文檔

https://github.com/tangbc/vue-virtual-scroll-list
https://nervjs.github.io/taro/docs/next/virtual-list/#itemcount-number-1


免責聲明!

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



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