解决 Element-ui中 选择器(Select)因options 数据量大导致渲染慢、页面卡顿的问题

简介: 解决 Element-ui中 选择器(Select)因options 数据量大导致渲染慢、页面卡顿的问题

业务场景:服务端返回两万多条数据需要在下拉框中展示,直接渲染会导致页面卡顿且需要很长时间等待,用户体验极差,所以我们把这个el-select优化一下,直接上代码。

相关知识传送门:

Vue实现自定义指令(directive)及应用场景

Vue中 实现函数的防抖、节流及应用场景

<template>
  <div class="content">
    <el-select v-model="chooseValue" filterable v-el-select-loadmore="loadMore(rangeNumber)">
      <el-option
        v-for="(item, index) in options.slice(0, rangeNumber)"
        :key="index"
        :label="item.label"
        :value="item.value">
      </el-option>
    </el-select>
  </div>
</template>
<script>
export default {
  data() {
    return {
      chooseValue: "",
      options: [],
      rangeNumber: 10,
    };
  },
  methods: { 
    getList() {
      // 测试数据25000条数据, 这里数据多少条无所谓,options.slice(0, rangeNumber)方法只会默认加载初始的10条数据
      for (let i = 0; i < 25000; i++) {
        this.options.push({label: "选择"+i,value:"选择"+i});
      } 
    },
    loadMore(n) {
      // n是默认初始展示的条数会在渲染的时候就可以获取,具体可以打log查看
      // elementui下拉超过7条才会出滚动条,如果初始不出滚动条无法触发loadMore方法
      return () => (this.rangeNumber += 5); // 每次滚动到底部可以新增条数  可自定义
    },
  },
  beforeMount() {
    this.getList();
  },
  directives:{
    'el-select-loadmore':(el, binding) => {
      // 获取element-ui定义好的scroll盒子
      const SELECTWRAP_DOM = el.querySelector(".el-select-dropdown .el-select-dropdown__wrap");
      if(SELECTWRAP_DOM){
        SELECTWRAP_DOM.addEventListener("scroll", function () {
          /**
           * scrollHeight 获取元素内容高度(只读)
           * scrollTop 获取或者设置元素的偏移值,
           *  常用于:计算滚动条的位置, 当一个元素的容器没有产生垂直方向的滚动条, 那它的scrollTop的值默认为0.
           * clientHeight 读取元素的可见高度(只读)
           * 如果元素滚动到底, 下面等式返回true, 没有则返回false:
           * ele.scrollHeight - ele.scrollTop === ele.clientHeight;
           */
          const condition = this.scrollHeight - this.scrollTop <= this.clientHeight;
          if (condition) binding.value();
        });
      }
    },
  }
};
</script>

最后, 两万多条数据用户不可能一直滚动下去找自己想要数据,记得设置 filterable 属性,实现搜索功能;

2020062310470442.png

问题: 如果仅设置 element-ui 的 filterable 属性 ,那么搜索的范围只有懒加载已滚动出的数据,导致搜索不全、不准确。

2020062310470442.png

为了解决这个问题,我们又继续使用了 filter-method 属性并结合 visible-change 事件,以及搜索输入时增加防抖进行优化。

最终代码:

// utils.js
function _debounce(fn, delay = 300) {
  var timer = null;
  return function () {
    var _this = this;
    var args = arguments;
    if (timer) clearTimeout(timer); 
    timer = setTimeout(function () {
      fn.apply(_this, args);
    }, delay);
  };
}
export {
  _debounce
}
<template>
  <div class="content">
    <el-select 
      v-model="chooseValue" clearable filterable :filter-method="filterMethod" 
      v-el-select-loadmore="loadMore(rangeNumber)"
      @visible-change="visibleChange">
      <el-option
        v-for="(item, index) in options.slice(0, rangeNumber)"
        :key="index"
        :label="item.label"
        :value="item.value">
      </el-option>
    </el-select>
  </div>
</template>
<script>
import {_debounce} from '@/utils/index.js'
export default {
  data() {
    return {
      chooseValue: "",
      options: [],
      rangeNumber: 10,
      resOptions:[],
    };
  },
  methods: { 
    // 模拟获取大量数据
    getList() {
      // 测试数据15000条数据, 这里数据多少条无所谓,options.slice(0, rangeNumber)方法只会默认加载初始的10条数据
      for (let i = 0; i < 25000; i++) {
        this.resOptions.push({label: "选择"+i,value:"选择"+i});
      } 
    },
    loadMore(n) {
      // n是默认初始展示的条数会在渲染的时候就可以获取,具体可以打log查看
      // elementui下拉超过7条才会出滚动条,如果初始不出滚动条无法触发loadMore方法
      return () => (this.rangeNumber += 5); // 每次滚动到底部可以新增条数  可自定义
    },
    // 筛选方法
    filterMethod:_debounce(function(filterVal){
      if(filterVal){
        let filterArr = this.resOptions.filter((item)=>{
          return item.label.toLowerCase().includes(filterVal.toLowerCase())
        })
        this.options = filterArr;
      }else{
        this.options = this.resOptions;
      }
    },500),
    // 下拉框出现时,调用过滤方法
    visibleChange(flag){
      if(flag){
        this.filterMethod()
      }
    },
  },
  beforeMount() {
    this.getList();
  },
  directives:{
    'el-select-loadmore':(el, binding) => {
      // 获取element-ui定义好的scroll盒子
      const SELECTWRAP_DOM = el.querySelector(".el-select-dropdown .el-select-dropdown__wrap");
      if(SELECTWRAP_DOM){
        SELECTWRAP_DOM.addEventListener("scroll", function () {
          /**
           * scrollHeight 获取元素内容高度(只读)
           * scrollTop 获取或者设置元素的偏移值,
           *  常用于:计算滚动条的位置, 当一个元素的容器没有产生垂直方向的滚动条, 那它的scrollTop的值默认为0.
           * clientHeight 读取元素的可见高度(只读)
           * 如果元素滚动到底, 下面等式返回true, 没有则返回false:
           * ele.scrollHeight - ele.scrollTop === ele.clientHeight;
           */
          const condition = this.scrollHeight - this.scrollTop <= this.clientHeight;
          if (condition) binding.value();
        });
      }
    },
  }
};
</script>

效果:

2020062310470442.png




相关文章
|
8月前
|
前端开发 安全 开发工具
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
410 90
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
10月前
|
存储
「Mac畅玩鸿蒙与硬件34」UI互动应用篇11 - 颜色选择器
本篇将带你实现一个颜色选择器应用。用户可以从预设颜色中选择,或者通过输入颜色代码自定义颜色来动态更改界面背景。该应用展示了如何结合用户输入、状态管理和界面动态更新的功能。
225 3
「Mac畅玩鸿蒙与硬件34」UI互动应用篇11 - 颜色选择器
|
11月前
|
UED
「Mac畅玩鸿蒙与硬件28」UI互动应用篇5 - 滑动选择器实现
本篇将带你实现一个滑动选择器应用,用户可以通过滑动条选择不同的数值,并实时查看选定的值和提示。这是一个学习如何使用 Slider 组件、状态管理和动态文本更新的良好实践。
145 1
「Mac畅玩鸿蒙与硬件28」UI互动应用篇5 - 滑动选择器实现
|
前端开发 JavaScript UED
element-ui 表格数据究竟隐藏着怎样的神秘样式与格式化技巧?快来揭开谜底!
【8月更文挑战第22天】《element-ui 表格数据样式及格式化案例》展示了如何利用 element-ui 的表格组件实现美观且易读的数据展示。通过简单配置,可以自定义表格样式,如边框、背景色等,并通过 formatter 实现数据格式化,例如将成绩保留一位小数。此外,还能依据条件设置行样式,如成绩达优则高亮显示,从而增强用户体验和数据可读性。
243 1
Element UI【级联选择器】el-cascader 获取选中内容的 label 数据,鼠标悬浮显示超长内容
Element UI【级联选择器】el-cascader 获取选中内容的 label 数据,鼠标悬浮显示超长内容
1539 3
Element UI 多选表格【翻页多选】简易版(不支持翻页多选数据反显)
Element UI 多选表格【翻页多选】简易版(不支持翻页多选数据反显)
289 0
Element UI 多选表格【翻页多选】简易版(不支持翻页多选数据反显)
软件研发核心问题之在需求拆解过程中,“数据与UI如何关联”的问题如何解决
软件研发核心问题之在需求拆解过程中,“数据与UI如何关联”的问题如何解决
130 0
|
安全 前端开发 数据安全/隐私保护
会员系统03-前台系统UI,利用页面展示大宗农产品价格走势曲线,添加银行卡,前还要进行实名认证,密码密文,隐私安全
会员系统03-前台系统UI,利用页面展示大宗农产品价格走势曲线,添加银行卡,前还要进行实名认证,密码密文,隐私安全
Element UI 多选表格【翻页多选】全能版(含翻页多选数据反显、toggleRowSelection失效的原因解析和解决方案)
Element UI 多选表格【翻页多选】全能版(含翻页多选数据反显、toggleRowSelection失效的原因解析和解决方案)
943 0
|
5月前
|
开发框架 前端开发 JavaScript
【HarmonyOS Next之旅】基于ArkTS开发(二) -> UI开发一
本文介绍了方舟开发框架(ArkUI)及其两种开发范式:基于ArkTS的声明式开发范式和类Web开发范式。ArkUI是用于构建HarmonyOS应用界面的UI框架,提供极简UI语法和基础设施。声明式开发范式使用ArkTS语言,以组件、动画和状态管理为核心,适合复杂团队协作;类Web开发范式采用HML、CSS、JavaScript三段式开发,适用于简单界面应用,贴近Web开发者习惯。文中还概述了两者的架构和基础能力,帮助开发者选择合适的范式进行高效开发。
167 15

热门文章

最新文章