日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

jq 下拉加载每次只执行一次_记一次 无限列表 滚动优化

發布時間:2025/3/15 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jq 下拉加载每次只执行一次_记一次 无限列表 滚动优化 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

背景

長列表優化, 是頁面性能優化中的一個比較常見的問題,也是面試中的常客。

剛好最近在的項目中, 遇到了一個長列表的性能問題,試過多種方案, 最后得以解決。

今天就給大家分享一下。

正文

場景描述

用戶需要批量修改 Product中 sku 的 映射關系,可以選擇的 Product 的 數量不限。

每一條sku 對應如下結構:

因為可以選擇的sku數量是不限的, 又不能分頁, 只能做到一個列表里。

于是, 長列表出現了。

剛開始的方案是做一個虛擬列表。

具體就是通過監聽sroll事件,每次滾動后計算一般元素位置(top和height)

然后,通過渲染三屏的方式,把一段數據渲染到頁面上。

數據量不多的時候, 沒什么問題。

當選擇幾百上千條sku 的時候, 快速滑動, 就開始出現卡頓。

如圖所示:

快速滾動出現空白

作為對比,看一下優化后的效果:

優化之后

問題定位

在chrome調試工具下,邊拖動列表邊觀察dom的變化。

發現,dom的卸載/掛載/更新的情況都出奇地慢,鼠標已經停下來,能明顯感覺到過一會dom才裝載完成,所以很可能是dom的渲染性能問題。

定位到渲染性能有問題的dom身上,即每一個 Item(renderFakeTable)。

使用普通文本代替Item,在同樣多數量的列表情況下,簡單的dom明顯會順暢很多,但是,仍然會出現空白問題。

繼續觀察renderFakeTable中的每一個元素(可以借用devTools Profiler)。

最簡單粗暴的方式就是去除某一類的組件,然后通過不斷自測的方式,找出最有可能影響渲染效率的元素:

SearchSelect(基于antd的Select封裝的一個業務組件)。

所以,影響渲染性能的元素很可能就是它。

渲染性能

除了組件的問題,還有可能是渲染的問題。

首先,原來無限滾動的邏輯就是基于scroll事件,通過不斷滾動觸發的回調,重新計算渲染到頁面上的區間。

其次,為了動態調整可視區域的元素,使用了MutationObserver。

導致空白問題則會有這幾種可能:

  • 沒加防抖,頻繁渲染帶來性能消耗
  • scroll 和 MutationObserver 相繼執行了渲染,導致dom出現了跳動的現象。
  • 預留的元素個數,viewPrepareCount太小了,導致拖動太快時,后面或前面都沒有多余的可見元素
  • 沒有開啟GPU加速,應該使用transform代替top來定位到正確位置
  • 不幸運的是,以上的可能都一一排除后,發現幾乎沒有啥提升。

    其實,在第二點縮小范圍時,應該意識到,空白問題/拖動不流暢均是因為渲染性能低下導致的

    測試驗證

    1. 虛擬列表 rc-virtual-list

    為了驗證是Select 組件的問題,基于:

    rc-virtual-list

    做了一個在線 demo :????

    在線地址:https://codesandbox.io/s/optimistic-bartik-69ygc?file=/src/animation.tsx

    動態演示:

    這里渲染了1000 條記錄, 每條記錄里有5個select;

    默認使用的是 antd Select, 幾乎拉不動;

    切換到原生select之后, 如絲般順滑。

    由此可以確定,卡頓是 Slect 組件引起的。

    所以要減少渲染成本:

  • 減少自己的父組件渲染成本,React.memo/React.useMemo/React.useCallback.
  • 減少Select渲染成本(比較麻煩,而且效果不明顯。經過自測,僅僅是使用一個基礎的Select,rc無限滾動的情況下同樣發生了卡頓)
  • 2. 下拉懶加載

    基于 Intersection Observer 實現一個 下拉懶加載。

    利用 Intersection Observer 實現:

    在列表的底部(也可能是底部偏上的某個位置)插入一個observer-dom元素.

    通過Observer來觀測其是否在可視區域中,如果在,那么就往下加載更多的內容:

    初始狀態時,列表會多渲染幾條數據(兩屏數據),observer-dom元素一直被頂到底部.

    用戶往下滾動時,observer-dom元素“出現”在用戶視野。

    每次多加載一屏的數據,循環如此,直到整個列表都渲染到頁面上。

    在線demo: https://codesandbox.io/s/gundongjiazai-antd491-forked-vtchw?file=/index.js

    動態演示:

    選擇方案

  • 要么接受使用rc無限滾動的不夠流暢;
  • 要么使用 Intersection Observer 實現一個下拉懶加載的無限滾動效果
  • 最終采用下拉懶加載。


    總結

    通常,無限滾動的方案可以分為兩種:

    1. 虛擬長列表

    • 優點:可以保證渲染在頁面上的dom元素盡可能少

    • 缺點:如果沒有特殊處理(比如rc或鎖定滾動區域),快速滾動時,基本都會有閃動的情況(也就是本次的空白問題)

    2. 下拉懶加載

    • 優點:防止用戶快速拖動的出現閃動問題。再通過加一個loading效果,幫助優化體驗

    • 缺點:當用戶把列表拉到底,整個列表都會被渲染到頁面上

    在選擇虛擬長列表or下拉懶加載之間的取舍時,可以參考:

    如果閃動問題可以接受(組件渲染沒有太大性能問題),而且對dom數量要求很嚴格,那么選擇虛擬長列表會更好。

    如果閃動問題不能接受,而最終的dom數量能夠接受,那么選擇下拉藍加載會更好。

    無論是選擇虛擬長列表or下拉懶加載,在使用監聽scroll事件或者Intersetion Observer API之間的取舍時,可以參考:

    • scroll的事件回調會在主線程中被成千上萬次調用,盡管加了防抖
    • scroll的方式,需要不斷記錄scrollTop和元素高度

    而使用Intersetion Observer API,上述幾點的計算就可以省略了,優化工作交給了瀏覽器。如果不考慮IE 等, 它是一個不錯的選擇。

    內容就這么多, 希望對大家有所啟發。

    如有錯誤, 歡迎指正, 謝謝。

    總結

    以上是生活随笔為你收集整理的jq 下拉加载每次只执行一次_记一次 无限列表 滚动优化的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。