mirror of
https://github.com/Fabio286/antares.git
synced 2025-06-05 21:59:22 +02:00
refactor: ts and composition api for base components
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="vscroll-holder">
|
||||
<div ref="root" class="vscroll-holder">
|
||||
<div
|
||||
class="vscroll-spacer"
|
||||
:style="{
|
||||
@ -20,71 +20,77 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'BaseVirtualScroll',
|
||||
props: {
|
||||
items: Array,
|
||||
itemHeight: Number,
|
||||
visibleHeight: Number,
|
||||
scrollElement: {
|
||||
type: HTMLDivElement,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
topHeight: 0,
|
||||
bottomHeight: 0,
|
||||
visibleItems: [],
|
||||
renderTimeout: null,
|
||||
localScrollElement: null
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
scrollElement () {
|
||||
this.setScrollElement();
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.setScrollElement();
|
||||
},
|
||||
beforeUnmount () {
|
||||
this.localScrollElement.removeEventListener('scroll', this.checkScrollPosition);
|
||||
},
|
||||
methods: {
|
||||
checkScrollPosition (e) {
|
||||
clearTimeout(this.renderTimeout);
|
||||
<script setup lang="ts">
|
||||
import { onBeforeUnmount, onMounted, Ref, ref, watch } from 'vue';
|
||||
|
||||
this.renderTimeout = setTimeout(() => {
|
||||
this.updateWindow(e);
|
||||
}, 200);
|
||||
},
|
||||
updateWindow () {
|
||||
const visibleItemsCount = Math.ceil(this.visibleHeight / this.itemHeight);
|
||||
const totalScrollHeight = this.items.length * this.itemHeight;
|
||||
const offset = 50;
|
||||
|
||||
const scrollTop = this.localScrollElement.scrollTop;
|
||||
|
||||
const firstVisibleIndex = Math.floor(scrollTop / this.itemHeight);
|
||||
const lastVisibleIndex = firstVisibleIndex + visibleItemsCount;
|
||||
const firstCutIndex = Math.max(firstVisibleIndex - offset, 0);
|
||||
const lastCutIndex = lastVisibleIndex + offset;
|
||||
|
||||
this.visibleItems = this.items.slice(firstCutIndex, lastCutIndex);
|
||||
|
||||
this.topHeight = firstCutIndex * this.itemHeight;
|
||||
this.bottomHeight = totalScrollHeight - this.visibleItems.length * this.itemHeight - this.topHeight;
|
||||
},
|
||||
setScrollElement () {
|
||||
if (this.localScrollElement)
|
||||
this.localScrollElement.removeEventListener('scroll', this.checkScrollPosition);
|
||||
|
||||
this.localScrollElement = this.scrollElement ? this.scrollElement : this.$el;
|
||||
this.updateWindow();
|
||||
this.localScrollElement.addEventListener('scroll', this.checkScrollPosition);
|
||||
}
|
||||
const props = defineProps({
|
||||
items: Array,
|
||||
itemHeight: Number,
|
||||
visibleHeight: Number,
|
||||
scrollElement: {
|
||||
type: HTMLDivElement,
|
||||
default: null
|
||||
}
|
||||
});
|
||||
|
||||
const root = ref(null);
|
||||
const topHeight: Ref<number> = ref(0);
|
||||
const bottomHeight: Ref<number> = ref(0);
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const visibleItems: Ref<any[]> = ref([]);
|
||||
const renderTimeout: Ref<NodeJS.Timeout> = ref(null);
|
||||
const localScrollElement: Ref<HTMLDivElement> = ref(null);
|
||||
const scrollElement = ref(props.scrollElement);
|
||||
|
||||
const checkScrollPosition = () => {
|
||||
clearTimeout(renderTimeout.value);
|
||||
|
||||
renderTimeout.value = setTimeout(() => {
|
||||
updateWindow();
|
||||
}, 200);
|
||||
};
|
||||
|
||||
const updateWindow = () => {
|
||||
const visibleItemsCount = Math.ceil(props.visibleHeight / props.itemHeight);
|
||||
const totalScrollHeight = props.items.length * props.itemHeight;
|
||||
const offset = 50;
|
||||
|
||||
const scrollTop = localScrollElement.value.scrollTop;
|
||||
|
||||
const firstVisibleIndex = Math.floor(scrollTop / props.itemHeight);
|
||||
const lastVisibleIndex = firstVisibleIndex + visibleItemsCount;
|
||||
const firstCutIndex = Math.max(firstVisibleIndex - offset, 0);
|
||||
const lastCutIndex = lastVisibleIndex + offset;
|
||||
|
||||
visibleItems.value = props.items.slice(firstCutIndex, lastCutIndex);
|
||||
|
||||
topHeight.value = firstCutIndex * props.itemHeight;
|
||||
bottomHeight.value = totalScrollHeight - visibleItems.value.length * props.itemHeight - topHeight.value;
|
||||
};
|
||||
|
||||
const setScrollElement = () => {
|
||||
if (localScrollElement.value)
|
||||
localScrollElement.value.removeEventListener('scroll', checkScrollPosition);
|
||||
|
||||
localScrollElement.value = scrollElement.value ? scrollElement.value : root.value;
|
||||
updateWindow();
|
||||
localScrollElement.value.addEventListener('scroll', checkScrollPosition);
|
||||
};
|
||||
|
||||
watch(scrollElement, () => {
|
||||
setScrollElement();
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
setScrollElement();
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
localScrollElement.value.removeEventListener('scroll', checkScrollPosition);
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
updateWindow
|
||||
});
|
||||
|
||||
</script>
|
||||
|
Reference in New Issue
Block a user