feat: custom models
This commit is contained in:
@@ -10,11 +10,34 @@ const props = defineProps<{
|
||||
prerender?: number;
|
||||
}>();
|
||||
|
||||
const containerRef = ref<HTMLElement | null>(null);
|
||||
const scrollMargin = ref(0);
|
||||
|
||||
const updateScrollMargin = () => {
|
||||
if (containerRef.value && props.scrollElement) {
|
||||
const containerRect = containerRef.value.getBoundingClientRect();
|
||||
const scrollRect = props.scrollElement.getBoundingClientRect();
|
||||
scrollMargin.value = containerRect.top - scrollRect.top + props.scrollElement.scrollTop;
|
||||
}
|
||||
};
|
||||
|
||||
const resizeObserver = new ResizeObserver(updateScrollMargin);
|
||||
|
||||
onMounted(() => {
|
||||
resizeObserver.observe(containerRef.value!);
|
||||
updateScrollMargin();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
resizeObserver.disconnect();
|
||||
});
|
||||
|
||||
const rowVirtualizer = useVirtualizer(computed(() => ({
|
||||
count: props.items.length,
|
||||
getScrollElement: () => props.scrollElement,
|
||||
estimateSize: () => props.minItemSize,
|
||||
overscan: props.overscan,
|
||||
scrollMargin: scrollMargin.value,
|
||||
getItemKey: (index: number) => props.keyField ? props.items[index]?.[props.keyField] || index : index,
|
||||
initialRect: {
|
||||
width: 0,
|
||||
@@ -31,8 +54,6 @@ const measureElement = (el: Element) => {
|
||||
}
|
||||
|
||||
rowVirtualizer.value.measureElement(el)
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
watch(() => props.items, () => {
|
||||
@@ -41,17 +62,17 @@ watch(() => props.items, () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :style="{ height: `${totalSize}px`, width: '100%', position: 'relative' }">
|
||||
<div ref="containerRef" :style="{ height: `${totalSize}px`, width: '100%', position: 'relative' }">
|
||||
<div v-for="virtualRow in virtualRows" :ref="(el) => measureElement(el as Element)"
|
||||
:key="(virtualRow.key as any | number)" :data-index="virtualRow.index" :style="{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '100%',
|
||||
height: `${virtualRow.size}`,
|
||||
transform: `translateY(${virtualRow.start}px)`,
|
||||
height: `${virtualRow.size}px`,
|
||||
transform: `translateY(${virtualRow.start - scrollMargin}px)`,
|
||||
}">
|
||||
<slot :item="props.items[virtualRow.index]" :index="virtualRow.index" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user