下拉数据过多,超过3000条浏览器卡顿

        JS是单线程,浏览器的处理和渲染能力都很差,碰到下拉框数据超过3000条就会有卡顿,基于element-UI的select我做了一个下拉框筛选的封装,可以控制前台显示下拉框中数据的数量

父组件使用案例:

  1.  formAttr 相当于v-model
  2.  options 下拉数据
  3. max 下拉框展示的条数
  4. 当下拉数据中属性不是value和label时,传一个myOptions,例:{value:'id',label:'text'}
<filter-select
    :formAttr.sync="form.name"
    :options="nameList"
    :max="10"
    :myOption="myOption"
>
</filter-select>

<script>
import filterSelect from '../modules/filterSelect.vue';
export defaule {
    components: { filterSelect },
    data() {
        return {
            form: {
                name: '',
              },
              nameList: [
                { id: 1, text: 'hello1' },
                { id: 2, text: 'hello2' },
                { id: 3, text: 'hello3' },
              ],
              myOption: { value: 'id', label: 'text' },
        },
    }
}
</script>

子组件HTML部分:

<template>
  <!-- 基于el-select对后台返回超大下拉数据处理 -->
  <el-select
    v-model="attr"
    filterable
    :clearable="clearable"
    :filter-method="selectFilter"
    :allow-create="allowCreate"
    :myOption="myOption"
    @change="change"
    @visible-change="visibleChange"
    @clear="clear"
    @blur="blur"
  >
    <el-option
      v-for="item in selectList"
      :key="item.value"
      :label="item.label"
      :value="item.value"
    ></el-option>
  </el-select>
</template>

JS部分

export default {
  /**
   * 使用案例:
   *  <filter-select
      :formAttr='form.name'
      :options='nameList'
      :max='100'
      :myOption='myOption'
    >
    </filter-select>
    父组件中data定义myOption,
    如果后台返回的下拉数据不是[{value:'hb',label:'河北'},{value:'bj',label:'北京'}]
                      而是[{proID:'hb',province:'河北'},{proID:'bj',province:'北京'}]
    此时就可以通过 myOption:{value:'province' , label:'proID'}
   */
  name: 'filterSelect',
  props: {
    // form表单的绑定值,比如 form.num
    formAttr: {
      required: true,
      type: [String, Number],
      default: '',
    },
    // 下拉数据的属性,一般为value和label,但也有不是的情况,比如返回的是id 和 text
    myOption: {
      type: Object,
      default: () => {
        return {
          value: 'value',
          label: 'label',
        };
      },
    },
    // 父组件传过来的下拉数据
    options: {
      required: true,
      default: () => [],
    },
    // 最多展示的条数
    max: {
      type: [Number, String],
      default: () => 50,
    },
    // 是否禁用
    disabled: {
      type: Boolean,
      default: () => false,
    },
    // 是否可以清空
    clearable: {
      type: Boolean,
      default: () => false,
    },
    // 是否支持创建条目
    allowCreate: {
      type: Boolean,
      default: () => false,
    },
  },
  computed: {},
  watch: {
    // 监听下拉框数据,发生变化执行下拉数据过滤截取
    options: {
      handler() {
        this.selectFilter();
      },
      deep: true,
    },
    formAttr:{
        handle(n){
            this.attr = n
        },
        immediate:true
    }
  },
  data() {
    return {
      attr: this.formAttr,
      selectList: [],
    };
  },
  methods: {
    // query是输入的值
    selectFilter(query = '') {
      let arr = this.options.map(obj => {
        return { value: obj[this.myOption.value], label: obj[this.myOption.label] };
      });
      console.log(arr);
      arr = arr.filter(item => {
        return (
          item.value.toString().toLowerCase().includes(query) ||
          item.label.toString().toLowerCase().includes(query)
        );
      });

      if (arr.length > this.max) {
        this.selectList = arr.splice(0, this.max);
      } else {
        this.selectList = arr;
      }
    },
    // 父组件事件可以直接参照 element-UI 的方法执行
    change(val) {
      this.$emit('update:formAttr',val)
      this.$emit('change', val);
    },
    // 下拉框出现/隐藏时触发
    visibleChange(val) {
      this.$emit('visibleChange', val);
    },
    // 可清空的单选模式下用户点击清空按钮时触发
    clear() {
      this.$emit('clear');
    },
    // 当 input 失去焦点时触发
    blur(e) {
      this.$emit('blur', e);
    },
    // 当 input 获得焦点时触发
    focus(e) {
      this.$emit('focus', e);
    },
  },
  mounted() {
    // this.selectList = this.options.map(item => {
    //   return { value: item[this.myOption.value], label: item[this.myOption.label] };
    // });
  },
};

it's over.

有哪里不理解的可以留言或者联系我,这个也可以改成输入内容向后端请求

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值