select懒加载解决el-option数量过多导致页面加载慢

需求:在一个dialog中使用了多个el-select提供选择用户、角色、部门等入口,但是每次打开弹框的时候都需要等很久才能将已选数据回显出来,而且在页面加载完成前鼠标无法操作dailog

解决方案:

  • 请求接口先获取到所有的option数组
  • 首次只截取10条option数据,避免option过多导致页面卡顿
  • 监听下拉框滚动事件,用户打开下拉框并滚动到下拉框底部后截取1-20条数据,以此类推
  • 考虑到需要回显的老数据,在截取数据后从所有option数组中找到已选的用户并unshift进去(如果截取的option中有已选数据就不用)

实现步骤:

先自定义一个监听select下拉框滚动的指令,通过

export default {
  mounted(el, { arg, value }) {
    const SELECTWRAP_DOM = document.querySelector(
      `.${arg} .el-select-dropdown__wrap`
    );
    SELECTWRAP_DOM &&
      SELECTWRAP_DOM.addEventListener("scroll", function () {
        const condition =
          SELECTWRAP_DOM.scrollHeight - SELECTWRAP_DOM.scrollTop ==
          SELECTWRAP_DOM.clientHeight;
        if (condition && SELECTWRAP_DOM.scrollTop > 0) {
          value();
        }
      });
  },
};

main.js中全局注册这个自定义指令


import selLazyLoad from '@/directive/common/selLazyLoad'

app.directive('selLazyLoad', selLazyLoad)

html结构:

    <el-select
          v-model="libyModel.user"
          multiple
          filterable
          v-selLazyLoad:[arg]="loadMore"
          :popper-class="arg"
          :filter-method="userFilterMethod"
          :reserve-keyword="false"
          placeholder="请选择"
          style="width: 100%"
          @change="changeLibyOpts('user')"
        >
          <el-option
            v-for="item in userOptList"
            :key="item.userId"
            :label="item.nickName"
            :value="item.userId"
            :disabled="item.disabled"
            >
            {{ item.nickName }}
          </el-option>
        </el-select>

定义方法:

const loadMore = () => {
  // 如果截取的长度==获取到的所有option长度将不再截取
  if (userOptList.value.length == userOptions.value?.length) return;
  userPageNum.value++;
  getScrollUser();
};

// 截取页面显示的实际option
const getScrollUser = () => {
  // 过滤出前十条用户信息+需要回显的数据
  userOptList.value = userOptions.value.slice(0, userPageNum.value * 10);
  if (libyModel.value.user?.length && userOptList.value?.length)
    libyModel.value.user.forEach((item) => {
      let hasOpt = userOptList.value.findIndex((val) => val.userId === item);
      if (hasOpt > -1) return;
      let findItem = userOptions.value.find((val) => val.userId === item);
      findItem &&
        userOptList.value.unshift({
          ...findItem,
        });
    });
};

// 搜索功能
const userFilterMethod = (value) => {
  // 手动触发下拉框回滚至顶部,避免触发v-slLazyLoad指令
  document.querySelector(
    `.${props.arg} .el-select-dropdown__wrap`
  ).scrollTop = 0;
  if (!value?.length) return getScrollUser();
  userOptList.value =
    userOptions.value.filter((item) => item.nickName?.includes(value)) || [];
};

在 Vue 的 Element UI 组件库中,`el-select` 提供了懒加载(Lazy Loading)功能和模糊查询(Filtering)特性,用于优化大量选项的性能和用户体验。 1. **懒加载(Lazy Loading)**: 懒加载适用于选项列表非常庞大,一次性加载所有数据可能导致页面加载的情况。当用户开始滚动下框时,`el-select` 只加载可视区域内的数据,其余部分的数据会在需要时动态请求。这通过 `lazy` 或 `load-data` 属性设置为一个函数,该函数接收当前选择项的索引作为参数,并返回一个Promise,当 Promise 解析后,新的数据才会被渲染到下菜单中。 ```html <el-select :lazy="true" v-model="selectedValue" @load-data="fetchOptions"> <el-option v-for="item in loadedOptions" :key="item.value" :label="item.label" :value="item.value"></el-option> </el-select> <script> export default { data() { return { selectedValue: '', loadedOptions: [], fetchData(index) { // 实现异步获取更多选项的逻辑 return new Promise((resolve) => setTimeout(() => resolve([...this.loadedOptions, ...moreOptions[index]]), 1000)); }, }; }, }; </script> ``` 2. **模糊查询(Filtering)**: `el-select` 自带的 `filter-method` 属性允许开发者自定义筛选选项的方式。当你输入搜索关键字时,这个方法会被调用,传入搜索关键词、选项数组以及当前选中的值。你可以在这里处理用户的输入,过滤出匹配的结果。 ```html <el-select filterable v-model="selectedValue" :filter-method="searchFn"> <el-option v-for="item in options" :key="item.id" :label="item.label" :value="item.value"></el-option> </el-select> <script> export default { methods: { searchFn(value, optionList, query) { // 这里可以根据query对optionList进行过滤 return optionList.filter(item => item.label.includes(query)); }, }, }; </script> ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值