virtual scroll table

This commit is contained in:
2024-05-21 13:29:09 +02:00
parent b81282b42e
commit 7a7dba010e
4 changed files with 154 additions and 72 deletions

View File

@@ -0,0 +1,64 @@
<script setup lang="ts">
import { useElementBounding, useVirtualList } from '@vueuse/core';
import { computed, ref } from 'vue';
interface Props {
list?: any[];
itemHeight: number;
headerHeight?: number;
bottom?: string;
}
const props = withDefaults(defineProps<Props>(), {
list: () => [],
});
const { list: values, containerProps, wrapperProps } = useVirtualList(computed(() => props.list), {
itemHeight: () => props.itemHeight,
})
const tableTop = ref<HTMLSpanElement | null>(null);
const { bottom: offset } = useElementBounding(tableTop);
const ypx = computed(() => {
let y = (offset.value ?? 0) + 'px';
if (props.bottom) {
y = `calc(${y} + ${props.bottom})`;
}
return y;
})
const scrollBarTop = computed(() => {
const h = props.headerHeight ?? props.itemHeight ?? 0;
return h + 'px';
})
</script>
<template>
<span ref="tableTop" class="h-0" />
<div v-if="list.length > 0" v-bind="containerProps" class="table-container">
<table v-bind="wrapperProps">
<slot :list="values" />
</table>
</div>
<slot v-else name="empty" />
</template>
<style scoped lang="postcss">
div.table-container {
@apply bg-slate-600;
max-height: calc(100vh - v-bind(ypx));
:deep(>table) {
@apply bg-slate-800;
>thead {
@apply sticky top-0 z-10;
top: -1px;
}
}
&::-webkit-scrollbar-track {
margin-top: v-bind(scrollBarTop);
}
}
</style>