针对ant-design-vue的select组件,实现大量数据时下拉框滚动时动态加载数据

antdv的select组件原本是有对大量数据的虚拟滚动的,但是貌似与:dropdownMatchSelectWidth="false"冲突,因此暂且尝试实现了一下动态加载数据。实现的效果不太理想,但也能凑合用,主要问题是无法通过滚动条快速滑动到指定位置,以及无法快速连贯滚动。

<template>
  <Select
    style="width: 200px"
    :onSelect="{()=>{console.log('自行实现相关逻辑')}}"
    :options="curFileList"
    placeholder="请选择"
    :onPopupScroll="handlePopupScroll"
  />
</template>
<script lang="ts" setup>
import { Select } from "ant-design-vue";
import axios from "axios";
import { nextTick, onMounted, Ref, ref } from "vue";

//总列表
const fileList: Ref<{ value: string; label: string }[]> = ref([]);
//下拉框中列表始终维持在这个长度,保持前端始终仅有一条看不到,也就是滑动高度仅有一条数据的高度
const curListSize = 9;
//当前下拉框所使用的curListSize条数据
const curFileList: Ref<{ value: string; label: string }[]> = ref([]);
//fileList中下一个放入curFileList的元素的检索地址
let fileIndex = 0;

onMounted(() => {
  loadData();
});
function loadData() {
  axios({
    method: "get",
    url: "/getFileList",
  }).then((res) => {
    const data = res.data.payload;
    if (data) {
      for (let i = 0; i < data.length; i++) {
        const op = {
          value: data[i].value,
          label: data[i].label,
        };
        fileList.value.push(op);
      }
      //初始化下拉框数据
      curFileList.value = fileList.value.slice(0, curListSize);
      fileIndex =
        curListSize < fileList.value.length
          ? curListSize
          : fileList.value.length;
    } else {
      alert("数据获取失败");
    }
  });
}

//动态加载下拉框数据,debounce的第二个参数用来设置触发频率
const handlePopupScroll = debounce(function (e) {
  const { target } = e;
  // scrollHeight:代表包括当前不可见部分的元素的高度
  // scrollTop:代表当有滚动条时滚动条向下滚动的距离,也就是元素顶部被遮住的高度
  // clientHeight:包括padding但不包括border、水平滚动条、margin的元素的高度
  const rmHeight = target.scrollHeight - target.scrollTop;
  const clHeight = target.clientHeight;
  // 当下拉框失焦的时候,也就是不下拉的时候
  if (rmHeight === 0 && clHeight === 0) {
    return;
  } else {
    // 当下拉框滚动条到达底部或者到达顶部或者总数不够换页的时候,不进行操作
    // 当滚动到当前页底部的时候就向curFileList尾部加入下一条数据,删除list头部一条数据;当滚动到当前页顶部时头部加入一条数据,删除list尾部一条数据
    if (
      (fileIndex >= fileList.value.length &&
        target.scrollTop > target.scrollHeight - clHeight - 0.1) ||
      (fileIndex <= curListSize && target.scrollTop < 0.1) ||
      fileList.value.length <= curListSize
    ) {
      return;
    } else {
      if (target.scrollTop > target.scrollHeight - clHeight - 0.1) {
        let temp = curFileList.value.concat(fileList.value[fileIndex]);
        temp.splice(0, 1);
        curFileList.value = temp;
        //数据更新后滚动到更新前位置
        nextTick(() => {
          target.scrollTo(0, 0.15);
        });
        fileIndex++;
      }
      if (target.scrollTop < 0.1) {
        let temp = curFileList.value;
        temp.splice(0, 0, fileList.value[fileIndex - curListSize - 1]);
        temp.splice(curListSize, 1);
        curFileList.value = temp;
        nextTick(() => {
          target.scrollTo(0, target.scrollHeight - clHeight - 0.15);
        });
        fileIndex--;
      }
    }
  }
}, 25);
</script>

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值