虛擬滾動(dòng)技術(shù) --- 解決加載大量列表DOM導(dǎo)致頁(yè)面卡頓

網(wǎng)頁(yè)dom元素過(guò)多為什么會(huì)導(dǎo)致頁(yè)面卡頓

1、dom過(guò)多,占用過(guò)多的內(nèi)存。
2、操縱dom時(shí)觸發(fā)重排重繪,消耗瀏覽器性能。特別是每一次滾動(dòng)事件將會(huì)讓對(duì)應(yīng) DOM 中的所有元素重新渲染。
3、資源加載阻塞,比如js資源放在body之前、行內(nèi)script阻塞、css加載會(huì)阻塞DOM樹渲染(css并不會(huì)阻塞DOM樹的解析)資源過(guò)大阻塞

至于第二個(gè)問(wèn)題,詳見網(wǎng)紅問(wèn)題--前端性能優(yōu)化(全流程) 或者 js回流和重繪

現(xiàn)在看來(lái),這兩點(diǎn)大條件是客觀存在的,我們無(wú)法改變,所以這時(shí)候解決的方案就呼之欲出了,別讓瀏覽器一次性渲染這么多元素,這里通常會(huì)對(duì)應(yīng)三種做法來(lái)減少元素渲染。

數(shù)據(jù)分頁(yè)

這個(gè)方案是大家瀏覽到頁(yè)面所常用的,通常在需要展示非常多行的數(shù)據(jù)時(shí)頁(yè)面會(huì)采用分頁(yè)的做法來(lái)分割數(shù)據(jù),但在SQL結(jié)果集的場(chǎng)景下并不是通用方案,原因是雖然該方法減少了一次性所渲染的行數(shù),但是如果查詢的表列數(shù)非常多的話,還是有很大概率需要渲染非常多的元素,所以不是一個(gè)穩(wěn)妥的選型。

無(wú)限滾動(dòng)

該方案的解決方法是第一次只渲染所能承受范圍內(nèi)的數(shù)據(jù)量,當(dāng)滾動(dòng)條拖動(dòng)接近底部(或右部)時(shí),再去追加下一批所需要渲染的元素,該方案也是有一個(gè)明顯的缺陷在于,無(wú)限地滾動(dòng)下去必然會(huì)觸及瀏覽器的性能瓶頸,而且所需要渲染的元素會(huì)越來(lái)越多,性能遲早會(huì)被拖垮。

虛擬滾動(dòng)

其實(shí)答案已經(jīng)隱藏在上面兩種解決方案里面了,數(shù)據(jù)分頁(yè)的方案是一次性渲染固定行數(shù)和列數(shù)的數(shù)據(jù)量,缺點(diǎn)是怕一次性的量就逼近上限。無(wú)限滾動(dòng)的方案是想看更多數(shù)據(jù)的時(shí)候再繼續(xù)渲染,不看就不渲染避免性能浪費(fèi),但缺點(diǎn)就在于只要一直觸發(fā)“繼續(xù)看”的操作,那么之前遺留的數(shù)據(jù)將會(huì)越來(lái)越多導(dǎo)致性能雪崩。

這時(shí)候可以把兩個(gè)方案中和一下,既然在有限的視窗中我們只能看到一部分的數(shù)據(jù),那么我們就通過(guò)計(jì)算可視范圍內(nèi)的單元格,這樣就保證了每一次拖動(dòng),我們渲染的 DOM 元素始終是可控的,不會(huì)像數(shù)據(jù)分頁(yè)方案怕一次性渲染過(guò)多,也不會(huì)發(fā)生無(wú)限滾動(dòng)方案中的老數(shù)據(jù)堆積現(xiàn)象。接下來(lái)我們用一張圖來(lái)表示虛擬滾動(dòng)的表現(xiàn)形式。

虛擬滾動(dòng)原理

根據(jù)圖中我們可以看到,無(wú)論我們?nèi)绾螡L動(dòng),我們可視區(qū)域的大小其實(shí)是不變的,那么要做到性能最大化就需要盡量少地渲染 DOM 元素,而這個(gè)最小值也就是可視范圍內(nèi)需要展示的內(nèi)容,也就是圖中的綠色區(qū)塊,在可視區(qū)域之外的元素均可以不做渲染。

可以通過(guò)如下幾步來(lái)實(shí)現(xiàn)虛擬滾動(dòng):

  • 每一行的高度需要相同,方便計(jì)算
  • 需要得知渲染的數(shù)據(jù)量(數(shù)組長(zhǎng)度),可基于總量和每個(gè)元素的高度計(jì)算出容器整體的所需高度,這樣就可以偽造一個(gè)真實(shí)的滾動(dòng)條
  • 獲取可視區(qū)域的高度
  • 在滾動(dòng)事件觸發(fā)后,滾動(dòng)條的距頂距離也可以理解為這個(gè)數(shù)據(jù)量中的偏移量,再根據(jù)可視區(qū)域本身的高度,算出本次偏移的截止量,這樣就得到了需要渲染的具體數(shù)據(jù)
  • 如果類似于渲染一個(gè)寬表,單行可橫向拆分為多列,那么在X軸上同理實(shí)現(xiàn)一次,就可以橫向的虛擬滾動(dòng)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 導(dǎo)讀 本文適用于以下三種讀者 只想要了解一下虛擬列表可閱讀“實(shí)現(xiàn)一個(gè)簡(jiǎn)單的虛擬列表”之前的部分 想初步探究虛擬列表...
    gjt19970425閱讀 22,331評(píng)論 0 17
  • 前言 場(chǎng)景是小程序長(zhǎng)列表優(yōu)化,框架基于mpvue,固定高度。(動(dòng)態(tài)高度暫時(shí)先不考慮) 關(guān)于recycle-view...
    依然還是或者其他閱讀 1,356評(píng)論 0 0
  • 0 前言 項(xiàng)目中某個(gè)頁(yè)面因業(yè)務(wù)要求會(huì)有很多圖片,加載速度不給力,用戶體驗(yàn)很差。在處理這個(gè)問(wèn)題的過(guò)程中,在網(wǎng)上參考了...
    0o刀刀o0閱讀 2,324評(píng)論 0 2
  • 為什么使用虛擬滾動(dòng) 相信在前端業(yè)務(wù)中不乏需要渲染長(zhǎng)列表的場(chǎng)景,當(dāng)渲染上千或者上萬(wàn)條數(shù)據(jù)時(shí),DOM操作是很昂貴的,一...
    Vv_Jiang閱讀 2,841評(píng)論 0 6
  • 當(dāng)我們遇到需要一次性向頁(yè)面插入十萬(wàn)條數(shù)據(jù)的情況下,該如何保證頁(yè)面不卡頓,維持一定的頁(yè)面渲染性能 ?? 場(chǎng)景:插入十萬(wàn)...
    Adder閱讀 1,760評(píng)論 1 5

友情鏈接更多精彩內(nèi)容