解决Element-ui中select下拉框因数据量大导致页面渲染慢、卡顿的问题

直接上代码:

1、写一个防抖的工具函数

tools.js

// 防抖
export const _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);
  };
}

2、下拉框的options数据源

citys.js(这里只写一少部分)

export default [
    {value: 110100, name: "北京市"},
    {value: 120100, name: "天津市"},
    {value: 130100, name: "石家庄市"},
    {value: 130200, name: "唐山市"},
    {value: 130300, name: "秦皇岛市"},
    {value: 130400, name: "邯郸市"},
    {value: 130500, name: "邢台市"},
    {value: 130600, name: "保定市"},
    {value: 130700, name: "张家口市"},
    {value: 130800, name: "承德市"},
    {value: 130900, name: "沧州市"},
    {value: 131000, name: "廊坊市"},
    {value: 131100, name: "衡水市"},
    {value: 140100, name: "太原市"},
    ......
]

3、业务代码

index.vue

<template>
  <div>
    <el-form :inline="true" :model="dataForm" size="small" class="h-search-form">
      <el-form-item>
        <el-select v-model="dataForm.cityCode" filterable :filter-method="filterMethod"
          v-el-select-loadmore="loadMore(rangeNumber)" @visible-change="visibleChange" placeholder="城市" clearable>
          <el-option :key="item.name + '' + i" :label="item.name" :value="item.value"
            v-for="(item, i) in citysList.slice(0, rangeNumber)"></el-option>
        </el-select>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
import { _debounce } from "@/utils/tools";
import citys from "../citys"
export default {

  data() {
    return {
      citysList: [],
      rangeNumber: 10,
      resOptions: citys,
      dataForm: {
        cityCode: ''
      }
    };
  },
  created() {
    this.filterMethod()
  },
  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();
        });
      }
    },
  },
  methods: {
    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.name.toLowerCase().includes(filterVal.toLowerCase())
        })
        this.citysList = filterArr;
      } else {
        this.citysList = this.resOptions;
      }
    }, 500),
    // 下拉框出现时,调用过滤方法
    visibleChange(flag) {
      if (flag) {
        this.filterMethod()
      }
    },
  }
};
</script>

4、效果

图片      图片        图片

 

posted @ 2025-09-11 16:52  web喵神  阅读(149)  评论(0)    收藏  举报