Ant Design Vue 中select 数据超大

468 阅读2分钟

前言

最近遇到select选项框数据量有好几千条的接口,本来想让后端处理下分页请求和模糊搜索,奈何这个后端技术太菜,跟我说不会,我滴乖乖,只好自己动手,解决了,在这把这个解决方式分享给大家,欢迎复制黏贴,然后摸鱼,哈哈哈。

一. 滚动加载处理

直接贴一下主要的select代码:

 <a-select
          @popupScroll="handlePopupScroll"
          show-search
          v-model:value="defaultValue"
          style="width: 80%"
          filter-option
          @change="selectChange"
          option-filter-prop="label"
          placeholder="请选择"
          @search="handleSearch"
          :options="Options" />

主要是利用@popupScroll="handlePopupScroll"这个属性方法来监听选择框的滚动

image.png

      const scrollPage = ref(1);
      const pageNumber = ref(100);
      const defaultValue = ref<string | undefined>(undefined);
      const formOptions = ref<SelectTypes['options']>([]);//接口获取的总数据
      const Options = ref<SelectTypes['options']>([]);
      
        const getAssists = async () => {
        const { data } = await api.workOrder.assistAll.request();
        formOptions.value = data.data.map((item) => {
          return { value: item.id, label: item.nickName };
        });
        Options.value = formOptions.value?.slice(0, 100);//默认取前100条数据
      };
      

   //下拉框下滑事件
      const handlePopupScroll = (e) => {
        const { target } = e;
        const scrollHeight = target.scrollHeight - target.scrollTop;
        const clientHeight = target.clientHeight;
        if (scrollHeight === 0 && clientHeight === 0) {
          scrollPage.value = 1;
        } else {
          if (scrollHeight < clientHeight + 5) {
            // console.log('滚动到底部拉');
            if (
              scrollPage.value >=
              Math.ceil((formOptions.value?.length as number) / pageNumber.value)
            ) {
              return;
            }
            scrollPage.value++;
            const startIndex = (scrollPage.value - 1) * pageNumber.value;
            const endIndex = startIndex + pageNumber.value;
            let newDataSlice;
            if (defaultValue.value) {
              // 模糊查询时,筛选包含关键字的选项
              newDataSlice = formOptions.value
                ?.filter((item: any) => item.label.includes(defaultValue.value))
                .slice(startIndex, endIndex);
            } else {
              newDataSlice = formOptions.value?.slice(startIndex, endIndex);
            }

            // 直接将新切片数据追加到 Options.value 数组中
            Options.value = Options.value?.concat(newDataSlice);
          }
        }
      };
  • scrollHeight:表示目标元素的内容高度减去滚动的距离。
  • clientHeight:表示目标元素的可见区域高度。

简单解释一下这个代码逻辑:

  1. 首先,通过判断 scrollHeight 是否小于 clientHeight + 5 来确定是否滚动到底部。这里的 5 是一个偏差值,用于处理滚动条滚动到底部时可能存在的一些浮点数计算不精确的情况。

  2. 如果滚动到底部,并且当前页数 scrollPage 没有超过总页数,则执行以下操作:

    • scrollPage 的值加1,表示进入下一页。

    • 计算新切片数据的起始索引 startIndex 和结束索引 endIndex

    • 根据是否存在 defaultValue 来确定使用不同的筛选方式获取新切片数据。如果存在 defaultValue,则只选择标签中包含关键字的选项。

    • 将新切片数据追加到 Options.value 数组中。

二.模糊搜索处理

    //记得防抖处理哦
   const handleSearch = debounce((value) => {
        defaultValue.value = value;
        if (value === '') {
          return Options.value;
        } else {
          Options.value = [];
          scrollPage.value = 1;
          Options.value = formOptions.value
            ?.filter((item: any) => item.label.includes(value))
            .slice(0, 100);
        }
      }, 300);

总结

朋友,你学废了吗?