feat(VirtualScroll): 虚拟滚动增加滚动到顶部, 底部, 指定项方法 (#3687)

This commit is contained in:
苗大 2024-03-25 14:24:29 +08:00 committed by GitHub
parent 9882e8df86
commit 7c52f083db
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 59 additions and 6 deletions

View File

@ -52,7 +52,7 @@
export default defineComponent({ export default defineComponent({
name: 'VirtualScroll', name: 'VirtualScroll',
props, props,
setup(props, { slots }) { setup(props, { slots, expose }) {
const wrapElRef = ref<HTMLDivElement | null>(null); const wrapElRef = ref<HTMLDivElement | null>(null);
const state = reactive({ const state = reactive({
first: 0, first: 0,
@ -128,6 +128,31 @@
state.last = getLast(state.first); state.last = getLast(state.first);
} }
function scrollToTop() {
const wrapEl = unref(wrapElRef);
if (!wrapEl) {
return;
}
wrapEl.scrollTop = 0;
}
function scrollToBottom() {
const wrapEl = unref(wrapElRef);
if (!wrapEl) {
return;
}
wrapEl.scrollTop = wrapEl.scrollHeight;
}
function scrollToItem(index: number) {
const wrapEl = unref(wrapElRef);
if (!wrapEl) {
return;
}
const i = index - 1 > 0 ? index - 1 : 0;
wrapEl.scrollTop = i * unref(getItemHeightRef);
}
function renderChildren() { function renderChildren() {
const { items = [] } = props; const { items = [] } = props;
return items.slice(unref(getFirstToRenderRef), unref(getLastToRenderRef)).map(genChild); return items.slice(unref(getFirstToRenderRef), unref(getLastToRenderRef)).map(genChild);
@ -143,6 +168,13 @@
); );
} }
expose({
wrapElRef,
scrollToTop,
scrollToItem,
scrollToBottom,
});
onMounted(() => { onMounted(() => {
state.last = getLast(0); state.last = getLast(0);
nextTick(() => { nextTick(() => {

View File

@ -4,8 +4,7 @@
.ant-input { .ant-input {
&-number, &-number,
&-number-group-wrapper { &-number-group-wrapper {
width: 100% !important; width: 100%;
min-width: 110px;
max-width: 100%; max-width: 100%;
} }
} }

View File

@ -1,8 +1,26 @@
<template> <template>
<PageWrapper class="virtual-scroll-demo"> <PageWrapper class="virtual-scroll-demo">
<Divider>基础滚动示例</Divider> <Divider>基础滚动示例</Divider>
<div class="text-center mb-4">
<a-button @click="vScrollRef?.scrollToTop()">滚动到顶部</a-button>
<a-button @click="vScrollRef?.scrollToBottom()" class="mx-2">滚动到底部</a-button>
<a-button @click="vScrollRef?.scrollToItem(scrollToItemIndex)"
>滚动到第
<input-number
v-model:value="scrollToItemIndex"
class="!w-60px mx-1"
:min="1"
:max="data.length"
:precision="0"
size="small"
:controls="false"
@keydown.enter="vScrollRef?.scrollToItem(scrollToItemIndex)"
/>
</a-button>
</div>
<div class="virtual-scroll-demo-wrap"> <div class="virtual-scroll-demo-wrap">
<VScroll :itemHeight="41" :items="data" :height="300" :width="300"> <VScroll :itemHeight="41" :items="data" :height="300" :width="300" ref="vScrollRef">
<template #default="{ item }"> <template #default="{ item }">
<div class="virtual-scroll-demo__item"> <div class="virtual-scroll-demo__item">
{{ item.title }} {{ item.title }}
@ -24,9 +42,13 @@
</PageWrapper> </PageWrapper>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { VScroll } from '@/components/VirtualScroll';
import { Divider } from 'ant-design-vue';
import { PageWrapper } from '@/components/Page'; import { PageWrapper } from '@/components/Page';
import { VScroll } from '@/components/VirtualScroll';
import { Divider, InputNumber } from 'ant-design-vue';
import { ref } from 'vue';
const vScrollRef = ref<typeof VScroll>();
const scrollToItemIndex = ref(1000);
const data = (() => { const data = (() => {
const arr: any[] = []; const arr: any[] = [];