淺析虛擬列表高性能渲染大體量數據原理


  在工作中,有時會遇到需要一些不能使用分頁方式來加載列表數據的業務情況,對於此,我們稱這種列表叫做長列表。比如,在一些外匯交易系統中,前端會實時的展示用戶的持倉情況(收益、虧損、手數等),此時對於用戶的持倉列表一般是不能分頁的。

  在淺析如何利用時間分片高性能渲染十萬級數據一文中,提到了可以使用時間分片的方式來對長列表進行渲染,但這種方式更適用於列表項的DOM結構十分簡單的情況。本文會介紹使用虛擬列表的方式,來同時加載大量數據。

一、為什么需要使用虛擬列表

  在實際的工作中,列表項必然不會僅僅只由一個li標簽組成,必然是由復雜DOM節點組成的。那么可以想象的是,當列表項數過多並且列表項結構復雜的時候,同時渲染時,會在Recalculate Style和Layout階段消耗大量的時間。

  而虛擬列表就是解決這一問題的一種實現。

二、什么是虛擬列表

  虛擬列表其實是按需顯示的一種實現,即只對可見區域進行渲染,對非可見區域中的數據不渲染或部分渲染的技術,從而達到極高的渲染性能

  假設有1萬條記錄需要同時渲染,我們屏幕的可見區域的高度為500px,而列表項的高度為50px,則此時我們在屏幕中最多只能看到10個列表項,那么在首次渲染的時候,我們只需加載10條即可。

  說完首次加載,再分析一下當滾動發生時,我們可以通過計算當前滾動值得知此時在屏幕可見區域應該顯示的列表項。

  假設滾動發生,滾動條距頂部的位置為150px,則我們可得知在可見區域內的列表項為第4項至第13項。

三、實現

  虛擬列表的實現,實際上就是在首屏加載的時候,只加載可視區域內需要的列表項,當滾動發生時,動態通過計算獲得可視區域內的列表項,並將非可視區域內存在的列表項刪除。

1、計算當前可視區域起始數據索引(startIndex)
2、計算當前可視區域結束數據索引(endIndex)
3、計算當前可視區域的數據,並渲染到頁面中
4、計算startIndex對應的數據在整個列表中的偏移位置startOffset並設置到列表上

  由於只是對可視區域內的列表項進行渲染,所以為了保持列表容器的高度並可正常的觸發滾動,將Html結構設計成如下結構:

<div class="infinite-list-container">
    <div class="infinite-list-phantom"></div>
    <div class="infinite-list">
      <!-- item-1 -->
      <!-- item-2 -->
      <!-- ...... -->
      <!-- item-n -->
    </div>
</div>
  • infinite-list-container可視區域的容器
  • infinite-list-phantom 為容器內的占位,高度為總列表高度,用於形成滾動條
  • infinite-list 為列表項的渲染區域

  接着,監聽infinite-list-containerscroll事件,獲取滾動位置scrollTop

  • 假定可視區域高度固定,稱之為screenHeight
  • 假定列表每項高度固定,稱之為itemSize
  • 假定列表數據稱之為listData
  • 假定當前滾動位置稱之為scrollTop

  則可推算出:

  • 列表總高度listHeight = listData.length * itemSize
  • 可顯示的列表項數visibleCount = Math.ceil(screenHeight / itemSize)
  • 數據的起始索引startIndex = Math.floor(scrollTop / itemSize)
  • 數據的結束索引endIndex = startIndex + visibleCount
  • 列表顯示數據為visibleData = listData.slice(startIndex,endIndex)

  當滾動后,由於渲染區域相對於可視區域已經發生了偏移,此時我需要獲取一個偏移量startOffset,通過樣式控制將渲染區域偏移至可視區域中。

  • 偏移量startOffset = scrollTop - (scrollTop % itemSize);

  本以為虛擬列表是個啥好東西,沒想到其實就是一個可視區域顯示的問題,很多方案對於動態不固定高度、網絡圖片以及用戶異常操作等形式處理的也並不好,了解下原理即可。更詳細的內容就看這篇吧,講的挺詳細的:列表優化之虛擬列表:https://www.jianshu.com/p/39404c94dbd0。

  其實我們墨天輪項目上在線文檔那個模塊 -文檔預覽的實現就用到了這一機制原理,比這個的交互還更為復雜(前預請求渲染、后預請求渲染、跳轉等等),貌似我還沒有寫博客,以后有時間再補上吧。


免責聲明!

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



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