Batch virtual item visibility updates
This commit is contained in:
@@ -103,6 +103,29 @@ export default function VirtualItem(props: VirtualItemProps) {
|
|||||||
const resolved = resolveChildren(() => props.children)
|
const resolved = resolveChildren(() => props.children)
|
||||||
const [isIntersecting, setIsIntersecting] = createSignal(true)
|
const [isIntersecting, setIsIntersecting] = createSignal(true)
|
||||||
const [measuredHeight, setMeasuredHeight] = createSignal(sizeCache.get(props.cacheKey) ?? 0)
|
const [measuredHeight, setMeasuredHeight] = createSignal(sizeCache.get(props.cacheKey) ?? 0)
|
||||||
|
let pendingVisibility: boolean | null = null
|
||||||
|
let visibilityFrame: number | null = null
|
||||||
|
const flushVisibility = () => {
|
||||||
|
if (visibilityFrame !== null) {
|
||||||
|
cancelAnimationFrame(visibilityFrame)
|
||||||
|
visibilityFrame = null
|
||||||
|
}
|
||||||
|
if (pendingVisibility !== null) {
|
||||||
|
setIsIntersecting(pendingVisibility)
|
||||||
|
pendingVisibility = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const queueVisibility = (nextValue: boolean) => {
|
||||||
|
pendingVisibility = nextValue
|
||||||
|
if (visibilityFrame !== null) return
|
||||||
|
visibilityFrame = requestAnimationFrame(() => {
|
||||||
|
visibilityFrame = null
|
||||||
|
if (pendingVisibility !== null) {
|
||||||
|
setIsIntersecting(pendingVisibility)
|
||||||
|
pendingVisibility = null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
const [hasMeasured, setHasMeasured] = createSignal(sizeCache.has(props.cacheKey))
|
const [hasMeasured, setHasMeasured] = createSignal(sizeCache.has(props.cacheKey))
|
||||||
const virtualizationEnabled = () => (props.virtualizationEnabled ? props.virtualizationEnabled() : true)
|
const virtualizationEnabled = () => (props.virtualizationEnabled ? props.virtualizationEnabled() : true)
|
||||||
|
|
||||||
@@ -167,7 +190,7 @@ export default function VirtualItem(props: VirtualItemProps) {
|
|||||||
}
|
}
|
||||||
const margin = props.threshold ?? DEFAULT_MARGIN_PX
|
const margin = props.threshold ?? DEFAULT_MARGIN_PX
|
||||||
intersectionCleanup = subscribeToSharedObserver(wrapperRef, targetRoot, margin, (entry) => {
|
intersectionCleanup = subscribeToSharedObserver(wrapperRef, targetRoot, margin, (entry) => {
|
||||||
setIsIntersecting(entry.isIntersecting)
|
queueVisibility(entry.isIntersecting)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,6 +246,7 @@ export default function VirtualItem(props: VirtualItemProps) {
|
|||||||
onCleanup(() => {
|
onCleanup(() => {
|
||||||
cleanupResizeObserver()
|
cleanupResizeObserver()
|
||||||
cleanupIntersectionObserver()
|
cleanupIntersectionObserver()
|
||||||
|
flushVisibility()
|
||||||
})
|
})
|
||||||
|
|
||||||
const wrapperClass = () => ["virtual-item-wrapper", props.class].filter(Boolean).join(" ")
|
const wrapperClass = () => ["virtual-item-wrapper", props.class].filter(Boolean).join(" ")
|
||||||
|
|||||||
Reference in New Issue
Block a user