ElementPlus的el-select滚动分页

45 阅读1分钟

背景

某一个下拉选项,数据太多了,需要通过滚动加载分页实现,异步加载数据

实现

el-select 结构

关键是这个 v-select-loadmore:[loadmoreClass]="loadMore"

<el-select
    v-model="xxx"
    filterable
    clearable
    placeholder="xxx"
    v-select-loadmore:[loadmoreClass]="loadMore"
    :popper-class="loadmoreClass"
  >
  <el-option
      v-for="(val, i) in options"
      :key="i"
      :label="val"
      :value="val"
    ></el-option>
  </el-select>

请求数据的方法

  const options = ref<string[]>([]);
  const PageSize = reactive({
    page: 1,
    size: 20,
    total: 0,
  });
// 加载数据
const loadData = async (keyword = '') => {
    try {
      const res = await fetchList({
        page: PageSize.page,
        size: PageSize.size,
      });
      if (res.code === 0) {
        options.value = [...options.value, ...res.data.lists];
        PageSize.total = res.data.total;
        PageSize.page++;
      } else {
        ElMessage.error(res.msg);
      }
    } catch (error) {
      console.error('加载失败', error);
    }
  };
  
  // 滚动触底加载
  const loadMore = () => {
    if (options.value.length < PageSize.total || PageSize.total === 0) loadData();
  };

定义一个指令方法

import { debounce } from "lodash";

export const selectLoadMore = {
  beforeMount(el, binding) {
    const selectDom = document.querySelector(
      `.${binding.arg} .el-select-dropdown__wrap`
    );

    const loadMores = debounce(() => {
      // 判断是否到底
      const isBase =
        selectDom.scrollHeight - selectDom.scrollTop - 10 <=
        selectDom.clientHeight;
      if (isBase) {
        // 可以增加防抖,用户体验会更好,视情况而定
        binding.value && binding.value();
      }
    }, 300);
    // 将获取到的dom和函数挂载到el-select上,以便实例销毁时进行事件移除处理
    el.selectDomInfo = selectDom;
    el.selectLoadMore = loadMores;
    // 监听滚动事件
    selectDom?.addEventListener("scroll", loadMores);
  },
  // 实例销毁
  beforeUnmount(el) {
    if (el.selectLoadMore) {
      el.selectDomInfo.removeEventListener("scroll", el.selectLoadMore);
      delete el.selectDomInfo;
      delete el.selectLoadMore;
    }
  },
};

定义指令

app.directive('selectLoadmore', selectLoadMore);