Quellcode durchsuchen

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

苗大 vor 1 Jahr
Ursprung
Commit
7c52f083db

+ 33 - 1
src/components/VirtualScroll/src/VirtualScroll.vue

@@ -52,7 +52,7 @@
   export default defineComponent({
     name: 'VirtualScroll',
     props,
-    setup(props, { slots }) {
+    setup(props, { slots, expose }) {
       const wrapElRef = ref<HTMLDivElement | null>(null);
       const state = reactive({
         first: 0,
@@ -128,6 +128,31 @@
         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() {
         const { items = [] } = props;
         return items.slice(unref(getFirstToRenderRef), unref(getLastToRenderRef)).map(genChild);
@@ -143,6 +168,13 @@
         );
       }
 
+      expose({
+        wrapElRef,
+        scrollToTop,
+        scrollToItem,
+        scrollToBottom,
+      });
+
       onMounted(() => {
         state.last = getLast(0);
         nextTick(() => {

+ 1 - 2
src/design/ant/input.less

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

+ 25 - 3
src/views/demo/comp/scroll/VirtualScroll.vue

@@ -1,8 +1,26 @@
 <template>
   <PageWrapper class="virtual-scroll-demo">
     <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">
-      <VScroll :itemHeight="41" :items="data" :height="300" :width="300">
+      <VScroll :itemHeight="41" :items="data" :height="300" :width="300" ref="vScrollRef">
         <template #default="{ item }">
           <div class="virtual-scroll-demo__item">
             {{ item.title }}
@@ -24,9 +42,13 @@
   </PageWrapper>
 </template>
 <script lang="ts" setup>
-  import { VScroll } from '@/components/VirtualScroll';
-  import { Divider } from 'ant-design-vue';
   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 arr: any[] = [];