acrobat 下拉列表 逻辑_记一次 无限列表 滚动优化
背景
長(zhǎng)列表優(yōu)化, 是頁(yè)面性能優(yōu)化中的一個(gè)比較常見(jiàn)的問(wèn)題,也是面試中的常客。
剛好最近在的項(xiàng)目中, 遇到了一個(gè)長(zhǎng)列表的性能問(wèn)題,試過(guò)多種方案, 最后得以解決。
今天就給大家分享一下。
正文
場(chǎng)景描述
用戶(hù)需要批量修改 Product中 sku 的 映射關(guān)系,可以選擇的 Product 的 數(shù)量不限。
每一條sku 對(duì)應(yīng)如下結(jié)構(gòu):
因?yàn)榭梢赃x擇的sku數(shù)量是不限的, 又不能分頁(yè), 只能做到一個(gè)列表里。
于是, 長(zhǎng)列表出現(xiàn)了。
剛開(kāi)始的方案是做一個(gè)虛擬列表。
具體就是通過(guò)監(jiān)聽(tīng)sroll事件,每次滾動(dòng)后計(jì)算一般元素位置(top和height)
然后,通過(guò)渲染三屏的方式,把一段數(shù)據(jù)渲染到頁(yè)面上。
數(shù)據(jù)量不多的時(shí)候, 沒(méi)什么問(wèn)題。
當(dāng)選擇幾百上千條sku 的時(shí)候, 快速滑動(dòng), 就開(kāi)始出現(xiàn)卡頓。
如圖所示:
快速滾動(dòng)出現(xiàn)空白作為對(duì)比,看一下優(yōu)化后的效果:
優(yōu)化之后問(wèn)題定位
在chrome調(diào)試工具下,邊拖動(dòng)列表邊觀察dom的變化。
發(fā)現(xiàn),dom的卸載/掛載/更新的情況都出奇地慢,鼠標(biāo)已經(jīng)停下來(lái),能明顯感覺(jué)到過(guò)一會(huì)dom才裝載完成,所以很可能是dom的渲染性能問(wèn)題。
定位到渲染性能有問(wèn)題的dom身上,即每一個(gè) Item(renderFakeTable)。
使用普通文本代替Item,在同樣多數(shù)量的列表情況下,簡(jiǎn)單的dom明顯會(huì)順暢很多,但是,仍然會(huì)出現(xiàn)空白問(wèn)題。
繼續(xù)觀察renderFakeTable中的每一個(gè)元素(可以借用devTools Profiler)。
最簡(jiǎn)單粗暴的方式就是去除某一類(lèi)的組件,然后通過(guò)不斷自測(cè)的方式,找出最有可能影響渲染效率的元素:
SearchSelect(基于antd的Select封裝的一個(gè)業(yè)務(wù)組件)。
所以,影響渲染性能的元素很可能就是它。
渲染性能
除了組件的問(wèn)題,還有可能是渲染的問(wèn)題。
首先,原來(lái)無(wú)限滾動(dòng)的邏輯就是基于scroll事件,通過(guò)不斷滾動(dòng)觸發(fā)的回調(diào),重新計(jì)算渲染到頁(yè)面上的區(qū)間。
其次,為了動(dòng)態(tài)調(diào)整可視區(qū)域的元素,使用了MutationObserver。
導(dǎo)致空白問(wèn)題則會(huì)有這幾種可能:
不幸運(yùn)的是,以上的可能都一一排除后,發(fā)現(xiàn)幾乎沒(méi)有啥提升。
其實(shí),在第二點(diǎn)縮小范圍時(shí),應(yīng)該意識(shí)到,空白問(wèn)題/拖動(dòng)不流暢均是因?yàn)殇秩拘阅艿拖聦?dǎo)致的
測(cè)試驗(yàn)證
1. 虛擬列表 rc-virtual-list
為了驗(yàn)證是Select 組件的問(wèn)題,基于:
rc-virtual-list
做了一個(gè)在線(xiàn) demo :????
在線(xiàn)地址:https://codesandbox.io/s/optimistic-bartik-69ygc?file=/src/animation.tsx
動(dòng)態(tài)演示:
這里渲染了1000 條記錄, 每條記錄里有5個(gè)select;
默認(rèn)使用的是 antd Select, 幾乎拉不動(dòng);
切換到原生select之后, 如絲般順滑。
由此可以確定,卡頓是 Slect 組件引起的。
所以要減少渲染成本:
2. 下拉懶加載
基于 Intersection Observer 實(shí)現(xiàn)一個(gè) 下拉懶加載。
利用 Intersection Observer 實(shí)現(xiàn):
在列表的底部(也可能是底部偏上的某個(gè)位置)插入一個(gè)observer-dom元素.
通過(guò)Observer來(lái)觀測(cè)其是否在可視區(qū)域中,如果在,那么就往下加載更多的內(nèi)容:
初始狀態(tài)時(shí),列表會(huì)多渲染幾條數(shù)據(jù)(兩屏數(shù)據(jù)),observer-dom元素一直被頂?shù)降撞?
用戶(hù)往下滾動(dòng)時(shí),observer-dom元素“出現(xiàn)”在用戶(hù)視野。
每次多加載一屏的數(shù)據(jù),循環(huán)如此,直到整個(gè)列表都渲染到頁(yè)面上。
在線(xiàn)demo: https://codesandbox.io/s/gundongjiazai-antd491-forked-vtchw?file=/index.js
動(dòng)態(tài)演示:
選擇方案
最終采用下拉懶加載。
總結(jié)
通常,無(wú)限滾動(dòng)的方案可以分為兩種:
1. 虛擬長(zhǎng)列表
優(yōu)點(diǎn):可以保證渲染在頁(yè)面上的dom元素盡可能少
缺點(diǎn):如果沒(méi)有特殊處理(比如rc或鎖定滾動(dòng)區(qū)域),快速滾動(dòng)時(shí),基本都會(huì)有閃動(dòng)的情況(也就是本次的空白問(wèn)題)
2. 下拉懶加載
優(yōu)點(diǎn):防止用戶(hù)快速拖動(dòng)的出現(xiàn)閃動(dòng)問(wèn)題。再通過(guò)加一個(gè)loading效果,幫助優(yōu)化體驗(yàn)
缺點(diǎn):當(dāng)用戶(hù)把列表拉到底,整個(gè)列表都會(huì)被渲染到頁(yè)面上
在選擇虛擬長(zhǎng)列表or下拉懶加載之間的取舍時(shí),可以參考:
如果閃動(dòng)問(wèn)題可以接受(組件渲染沒(méi)有太大性能問(wèn)題),而且對(duì)dom數(shù)量要求很?chē)?yán)格,那么選擇虛擬長(zhǎng)列表會(huì)更好。
如果閃動(dòng)問(wèn)題不能接受,而最終的dom數(shù)量能夠接受,那么選擇下拉藍(lán)加載會(huì)更好。
無(wú)論是選擇虛擬長(zhǎng)列表or下拉懶加載,在使用監(jiān)聽(tīng)scroll事件或者Intersetion Observer API之間的取舍時(shí),可以參考:
- scroll的事件回調(diào)會(huì)在主線(xiàn)程中被成千上萬(wàn)次調(diào)用,盡管加了防抖
- scroll的方式,需要不斷記錄scrollTop和元素高度
而使用Intersetion Observer API,上述幾點(diǎn)的計(jì)算就可以省略了,優(yōu)化工作交給了瀏覽器。如果不考慮IE 等, 它是一個(gè)不錯(cuò)的選擇。
內(nèi)容就這么多, 希望對(duì)大家有所啟發(fā)。
如有錯(cuò)誤, 歡迎指正, 謝謝。
總結(jié)
以上是生活随笔為你收集整理的acrobat 下拉列表 逻辑_记一次 无限列表 滚动优化的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: laravel 控制器 中间件 传递数据
- 下一篇: python自启动 绕过360_记录一次