解决el-select数据量过大的3种方案

 更新时间:2023年09月14日 08:39:27   作者:searchop  
最近做完一个小的后台管理系统,快上线了,发现一个问题,有2个select的选项框线上的数据量是1w+,而测试环境都是几百的,所以导致页面直接卡住了,本文给大家总结了3种方法,需要的朋友可以参考下

背景

最近做完一个小的后台管理系统,快上线了,发现一个问题,有2个select的选项框线上的数据量是1w+。。而测试环境都是几百的,所以导致页面直接卡住了,over了。

想了一下,如果接口支持搜索和分页,那直接通过上拉加载就可以了。但后端不太愿意改😄。行吧,前端搞也是可以的。

方案

通过一顿搜索加联想总结了3种方法,以下方法都需要支持开启filterable支持搜索。

标题具体问题
方案1只展示前100条数据,这个的话配合filter-method每次只返回前100条数据。限制展示的条数可能不全,搜索需要多搜索点内容
方案2分页方式,通过指令实现上拉加载,不断上拉数据展示数据。仅过滤加载出来的数据,需要配合filterMethod过滤数据
方案3options列表采用虚拟列表实现。成本高,需要引入虚拟列表组件或者自己手写

方案一,青铜段位 filterMethod直接过滤数据量

<template>
    <el-select 
      v-model="value" 
      clearable filterable 
      :filter-method="filterMethod">
      <el-option
        v-for="(item, index) in options.slice(0, 100)"
        :key="index"
        :label="item.label"
        :value="item.value">
      </el-option>
    </el-select>
 </template>
 export default {
  name: 'Demo',
  data() {
    return {
      options: [],
      value: ''
    }
  },
  beforeMount() {
    this.getList();
  },
  methods: {
    // 模拟获取大量数据
    getList() {
      for (let i = 0; i < 25000; i++) {
        this.options.push({label: "选择"+i,value:"选择"+i});
      } 
    },
    filterMethod(val) {
      console.log('filterMethod', val);
      this.options = this.options.filter(item => item.value.indexOf(val) > -1).slice(0, 100);
    },
    visibleChange() {
      console.log('visibleChange');
    }
  }
}

方案二、 白银段位 自定义滚动指令,实现翻页加载

写自定义滚动指令,options列表滚动到底部后,再加载下一页。但这时候筛选出来的是已经滚动出来的值。

这里如果直接使用filterable来搜索,搜索出来的内容是已经滑动出来的内容。如果想筛选全部的,就需要重写filterMethod方法来自定义过滤功能。可以根据情况选择是否要重写filterMethod。

<template>
  <div class="dashboard-editor-container">
    <el-select 
      v-model="value" 
      clearable
      filterable 
      v-el-select-loadmore="loadMore"
      :filter-method="filterMethod">
      <el-option
        v-for="(item, index) in options"
        :key="index"
        :label="item.label"
        :value="item.value">
      </el-option>
    </el-select>
  </div>
</template>
<script>
export default {
  name: 'Demo',
  data() {
    return {
      options: [],
      value: '',
      pageNo: 0
    }
  },
  beforeMount() {
    this.getList();
  },
  methods: {
    // 模拟获取大量数据
    getList() {
      const data = [];
      for (let i = 0; i < 25000; i++) {
        data.push({label: "选择"+i,value:"选择"+i});
      }
      this.allData = data;
      this.data = data;
      this.getPageList()
    },
    getPageList(pageSize = 10) {
      this.pageNo++;
      const list = this.data.slice(0, pageSize * (this.pageNo));
      this.options = list;
    },
    loadMore() {
      this.getPageList();
    },
    filterMethod(val) {
      this.data = val ? this.allData.filter(item => item.label.indexOf(val) > -1) : this.allData;
      this.getPageList();
    }
  },
  directives:{
    'el-select-loadmore':(el, binding) => {
      // 获取element-ui定义好的scroll父元素
      const wrapEl = el.querySelector(".el-select-dropdown .el-select-dropdown__wrap");
      if(wrapEl){
        wrapEl.addEventListener("scroll", function () {
          /**
           * scrollHeight 获取元素内容高度(只读)
           * scrollTop 获取或者设置元素的偏移值,
           *  常用于:计算滚动条的位置, 当一个元素的容器没有产生垂直方向的滚动条, 那它的scrollTop的值默认为0.
           * clientHeight 读取元素的可见高度(只读)
           * 如果元素滚动到底, 下面等式返回true, 没有则返回false:
           * ele.scrollHeight - ele.scrollTop === ele.clientHeight;
           */
          if (this.scrollTop + this.clientHeight >= this.scrollHeight) {
            // binding的value就是绑定的loadmore函数
            binding.value();
          }
        });
      }
    },
  },
}
</script>
</script>

方案三、黄金段位- 虚拟列表

引入社区的vue-virtual-scroll-list 支持虚拟列表。但这里想的自己再实现一遍虚拟列表,后续再写吧。

<template>
  <div class="dashboard-editor-container">
    <el-select 
      v-model="value" 
      clearable
      filterable >
      <virtual-list
          class="list"
          style="height: 360px; overflow-y: auto;"
          :data-key="'value'"
          :data-sources="data"
          :data-component="item"
          :estimate-size="50"
        />
    </el-select>
  </div>
</template>
<script>
import VirtualList from 'vue-virtual-scroll-list';
import Item from './item';
export default {
  name: 'Demo',
  components: {VirtualList, Item},
  data() {
    return {
      options: [],
      data: [],
      value: '',
      pageNo: 0,
      item: Item,
    }
  },
  beforeMount() {
    this.getList();
  },
  methods: {
    // 模拟获取大量数据
    getList() {
      const data = [];
      for (let i = 0; i < 25000; i++) {
        data.push({label: "选择"+i,value:"选择"+i});
      }
      this.allData = data;
      this.data = data;
      this.getPageList()
    },
    getPageList(pageSize = 10) {
      this.pageNo++;
      const list = this.data.slice(0, pageSize * (this.pageNo));
      this.options = list;
    },
    loadMore() {
      this.getPageList();
    }
  }
}
</script>
// item组件
<template>
    <el-option :label="source.label" :value="source.value"></el-option>
</template>
  <script>
  export default {
    name: 'item',
    props: {
      source: {
        type: Object,
        default() {
          return {}
        }
      }
    }
  }
  </script>
  <style scoped>
  </style>

总结

最后我们项目中使用的虚拟列表,为啥,因为忽然发现组件库支持select是虚拟列表,那就直接使用这个啦。

以上就是解决el-select数据量过大的3种方案的详细内容,更多关于el-select数据量过大的资料请关注脚本之家其它相关文章!

相关文章

  • 关于eslint和prettier格式化冲突问题

    关于eslint和prettier格式化冲突问题

    这篇文章主要介绍了eslint和prettier格式化冲突问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-08-08
  • 基于vue和bootstrap实现简单留言板功能

    基于vue和bootstrap实现简单留言板功能

    这篇文章主要为大家详细介绍了基于vue和bootstrap实现简单留言板功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-05-05
  • VUE3中Element table表头动态展示合计信息

    VUE3中Element table表头动态展示合计信息

    本文主要介绍了在Vue中实现动态合计两个字段并输出摘要信息的方法,通过使用监听器和深度监听,确保当数据变化时能正确更新合计结果,具有一定的参考价值,感兴趣的可以了解一下
    2024-11-11
  • vue3项目如何国际化实战指南

    vue3项目如何国际化实战指南

    像很多大型的网址,特别是跨国际等公司网页,访问来自世界各地用户,所以网页的国际化极其重要的需求,下面这篇文章主要给大家介绍了关于vue3项目如何国际化的相关资料,需要的朋友可以参考下
    2022-09-09
  • 详解Vue取消eslint语法限制

    详解Vue取消eslint语法限制

    本篇文章给大家分享了Vue取消eslint语法限制的相关知识点内容,有兴趣的朋友们可以参考学习下。
    2018-08-08
  • Vue-resource安装过程及使用方法解析

    Vue-resource安装过程及使用方法解析

    这篇文章主要介绍了Vue-resource安装过程及使用方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07
  • 在Linux服务器上部署vue项目

    在Linux服务器上部署vue项目

    这篇文章介绍了在Linux服务器上部署vue项目的方法,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-11-11
  • vue弹窗消息组件的使用方法

    vue弹窗消息组件的使用方法

    这篇文章主要为大家详细介绍了vue弹窗消息组件的使用方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-04-04
  • elementui el-calendar日历组件使用示例

    elementui el-calendar日历组件使用示例

    这篇文章主要为大家介绍了elementui el-calendar日历组件使用示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12
  • Vue3 Vant组件库使用过程中的避坑点

    Vue3 Vant组件库使用过程中的避坑点

    本片文章主要写了,Vue3开发时运用Vant UI库的一些避坑点。让有问题的小伙伴可以快速了解是为什么。也是给自己做一个记录
    2023-04-04

最新评论