数据量太大的select怎么办?

803 阅读1分钟

开发中会遇见超大数据量的筛选功能,而且后端接口是一股脑全部扔给前端,前端虽然有elementUi等的组件自带搜索功能,可是大数据量的筛选和dom创建会让页面异常卡顿。

1、筛选框需要一次展示那么多数据吗?

很显然是不需要的,一般的筛选框是给用户做选择用的,用户不会费力的使劲找,一般数据量大的筛选用户都会有目的的精确筛选,默认筛选给一个示例就行了

2、怎么做?

  1. 获取筛选框所有数据
  2. 截取50个左右的默认数据
  3. 输入搜索时候从全数据中检索并截取50个赋值给筛选框

示例代码(以iviewUI为例)

<template>
  <Select 
    :value="value"
    :placeholder="placeholder" 
    :default-label="defaultLabel" class="select-width" clearable filterable 
    :remote-method="remoteFilter"
    :style="{width:width+'px'}"
    @on-change="change" 
    @on-query-change="selectInput">
    <Option v-for="(val,k) in options" :key="k" :value="val[optionValue]" :disabled="!!val.disabled">{{ val[optionLabel] }}</Option>
  </Select>
</template>
/** 
 * 快速搜索组件
 * 传入源数据后,前端做搜索
 **/ 
export default {
  props: {
    value: { // model
      type: [Number,String],
      default: ''
    },
    list: { // 原数据
      type: Array
    },
    optionValue: {  // value
      type: String,
      default: 'value'
    },
    optionLabel: { // label
      type: String,
      default: 'label'
    },
    preOptions:{ // 预览展示的插入值
      type: Array,
      default:function() {
        return []
      }
    },
    placeholder: {
      type: String,
      default: '请选择或者搜索'
    },
    width:{ // 筛选框的宽度
      type:Number,
      default: 180
    },
    preNum: { // 展示个数
      type:Number,
      default: 66
    }
  },
  data() {
    return {
      options: [],
      defaultLabel:''
    }
  },
  mounted() {
    this.setDefaultLabel(this.value)
    this.remoteFilter(this.defaultLabel)
  },
  methods: {
    // 远端搜
    remoteFilter(query){
      if (query !== '') {
        let options = []
        this.list.forEach((e,i) => {
          e.showName.includes(query) && options.push(e)
        })
        options && options.length && (this.options = [...this.preOptions,...options])
      } else {
        let options = this.list.slice(0,this.preNum)
        this.options = [...this.preOptions,...options]
      }
    },
    // default-label
    setDefaultLabel(val){
      let O = this.list.find(e => e.name === val)
      O && (this.defaultLabel = O.showName || '')
    },
    // 清空后赋值默认
    selectInput(query){
      if(query === ''){
        let options = this.list.slice(0,this.preNum)
        this.options = [...this.preOptions,...options]
      }
    },
    // 选中
    change(e){
      this.$emit('on-change',e)
    }
  }
}
</script>