virtual scroll table
This commit is contained in:
64
src/components/table/VirtualScrollTable.vue
Normal file
64
src/components/table/VirtualScrollTable.vue
Normal 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>
|
||||
Reference in New Issue
Block a user