走近Fusion組件——無限滾動


Fusion Design體系在經歷阿里巴巴集團內部三年多的錘鍊後終於在上個月對外開放了,做爲設計系統的基礎骨架—— Next組件庫也在正式開源啦🎉🎉


Fusion Next(包名@alifd/next)是一個基於 React 實現,面向 PC 端的可配置組件庫。爲阿里集團2000+個項目服務的同時,沉澱出了很多基礎組件,如今已經達到50+。這個系列將經過實際需求場景,來介紹Fusion組件庫的各類有意思的功能、分析實現原理,歡迎討論👏

使用場景

長列表情境下,例如一個有上千條數據的商品類目選擇,初始化選項組時間較長,有明顯卡頓。

緣由分析

在React環境下,卡頓可能的緣由有不少種,例如隨意setState、未設置shouldComponentUpdate父組件更新引發全部子組件重繪、DOM節點多層級深致使HTML解析過慢等。在當前場景下,緣由顯然是最後一個,頁面DOM節點數過多,致使虛擬DOM的對比、渲染消耗過大,頁面卡頓。

解決方案

不管是IOS、Android客戶端,仍是H五、PC頁面,業內對於這種長列表的優化都有一致的呼聲—— 虛擬滾動
既然是DOM節點多致使的問題,那就減小節點數。頁面DOM結構設計不合理,須要優化DOM結構,移除沒必要要的節點,減小DOM操做耗費的資源。

效果

先來一組對比數據,對比的是從開始渲染到渲染結束所耗費的時長。從圖中能夠看出當數據量愈來愈大時,虛擬滾動表現突出,耗費的時間保持在80ms之內。


原理

屏幕高度有限,用戶每次看到的項可能只有十幾個,維護一個數組domArray,用來存放最終展現到頁面上的列表項,將待渲染列表項個數始終控制在必定範圍以內。在滾動時,根據縱向滾動的位置動態更新這個數組,並配合transform: translateY達到無限滾動的效果。


關鍵點有兩個:
  1. 列表體transform: translateY(offset) 值的變化
  2. 最終渲染到頁面上的數組domArray的更新規則

1. 相對位移如何變化

translateY(offset)可使所在元素相對父元素向下偏移offset。 jsfiddle.net/youluna/w6d…
用戶的上下滾動會引發可視區數組domArray包含元素的變化,當數組的首個元素從第 from 個切換爲 from+1 的時,整個列表看起來是向上瞬移了第from個元素的高度,這時利用translateY增長第from個元素的高度,就能維持 第 from+1 個元素在相對位置不變。


2. 數組什麼時候更新

domArray儲存着用戶可能會看到的那部分列表項,通常取自超長源數據中的一段[from, from + size] 例以下圖中的[36, 53]。
  • from值是如何來的?
爲保證domArray元素保持較少個數,須要記錄滾動距離scrollTop,在滾動時動態增刪數組內元素。保證以下公式成立,根據scrollTop的變化動態更新from的值:
前from個元素高度的加和 < 滾動距離scrollTop - bufferHeight < 前from + 1個元素高度的加和

  • from + size 值須要知足什麼要求?
要求[from, from + size] 這些元素渲染到頁面上的總高度(domsHeight)恰好大於可視區域高度(visibleHeight)+緩衝區(buffer*2)高度,即:
domsHeight > visibleHeight + bufferHeight*2
一旦高度條件不知足,就從新計算更新from、size的值,從而更新domArray。
domArray的更新與translateY值的改變相配合,營造視覺上接二連三的滾動效果。Fusion已內置 VirtualList組件,目前已經能夠與 Select組件Cascader組件配合使用,Table組件較爲複雜但也經過自身改造支持了無限滾動。

Fusion Next組件庫還有各類有意思的功能,期待你們發掘,快來體驗使用吧~ 👉 戳我查看 說到體驗使用,就想起了組件倉庫 github.com/alibaba-fus…,我將在github繼續扮演commiter,歡迎各位大佬前來把玩,issue/PR兩開花🐒🐒
相關文章
相關標籤/搜索