虛擬捲動
對於非常長的選項清單,虛擬捲動只渲染視野內的列加上少量緩衝,讓 DOM 保持輕量。
啟用
虛擬捲動是 opt-in。開啟它並提供與你樣式相符的固定列高:
js
createSelkitDom('#big', {
options: thousandsOfOptions,
virtualScroll: true,
itemHeight: 36, // px,須與實際渲染列高一致
})vue
<SelkitSelect :options="thousandsOfOptions" virtual-scroll :item-height="36" />jsx
<SelkitSelect options={thousandsOfOptions} virtualScroll itemHeight={36} />itemHeight 預設 36,對齊 base theme 的選項高度。請依你的主題實際渲染高度設定。
分組清單
虛擬捲動也支援 optgroup 式的分組。由於 group header 高度與 option 不同,需另外提供 groupHeight:
js
createSelkitDom('#big', {
options: groupedOptions,
virtualScroll: true,
itemHeight: 36, // option 列高
groupHeight: 28, // group 標題列高
})vue
<SelkitSelect :options="groupedOptions" virtual-scroll :item-height="36" :group-height="28" />jsx
<SelkitSelect options={groupedOptions} virtualScroll itemHeight={36} groupHeight={28} />groupHeight 預設 28(base theme 的標題高度)。與 itemHeight 一樣,請依你的主題實際 渲染高度設定,佔位計算才會準確。
group header 不會 sticky —— 捲進某組中段時,該組標題會跟著捲出。極端(10 萬+)清單 建議維持扁平;分組虛擬鎖定數千列以內。
運作方式
扁平清單用不碰 DOM 的核心輔助函式 computeVirtualRange,把捲動位置、視窗高度與單一列高 對應成該渲染的切片與上下佔位(O(1)):
ts
import { computeVirtualRange } from '@selkit/core'
computeVirtualRange({
scrollTop: 400,
viewportHeight: 260,
itemHeight: 36,
itemCount: 1000,
overscan: 4, // 選用的緩衝列數,預設 4
})
// → { startIndex, endIndex, paddingTop, paddingBottom }分組清單因列高不一,改用 computeVirtualWindow,吃每列高度陣列(標題列用 groupHeight, 其餘用 itemHeight),以累積偏移回傳相同形狀:
ts
import { computeVirtualWindow } from '@selkit/core'
computeVirtualWindow({
heights: [28, 36, 36, 28, 36], // group, opt, opt, group, opt
scrollTop: 100,
viewportHeight: 260,
overscan: 4,
})
// → { startIndex, endIndex, paddingTop, paddingBottom }每個 adapter 追蹤下拉浮層的 scrollTop,呼叫對應的輔助函式,並把回傳的切片(含 group header)渲染在兩個保留捲軸尺寸的佔位元素之間。同一套計算驅動三個 adapter,行為一致。