修改elment的下拉组件,满足大数量下拉

针对我们项目中经常会遇到下拉框在遇到大量数据时,加载会卡顿,用户体验感不好。针对该情况我对el-select组件做了一下修改,来满足这样大量数据下拉不卡顿。提高用户的体验感。

具体代码如下:

<template>
  <div>
    <el-select
      style="width: 100%"
      v-model="selectValue"
      :placeholder="selectProps.placeholder || '请选择'"
      size="mini"
      filterable
      :filter-method="delayFilter"
      @change="selectChange"
      v-selectloadmore="loadMore"
    >
      <el-option v-for="(item, index) in options"
       :key="item[selectProps.value || 'value'] + index"
       :label="item[selectProps.label || 'label']"
       :value="item[selectProps.value || 'value']"
      ></el-option>
    </el-select>
  </div>
</template>

<script>
import _ from 'lodash'
export default {
  name: 'large-data-select',
  directives: {
    'selectloadmore': {
      bind (el, binding) {
        // 获取element-ui定义好的scroll盒子
        const SELECTWRAP_DOM = el.querySelector('.el-select-dropdown .el-select-dropdown__wrap')
        SELECTWRAP_DOM.addEventListener('scroll', function () {
          /**
           * scrollHeight 获取元素内容高度(只读)
           * scrollTop 获取或者设置元素的偏移值,常用于, 计算滚动条的位置, 当一个元素的容器没有产生垂直方向的滚动条, 那它的scrollTop的值默认为0.
           * clientHeight 读取元素的可见高度(只读)
           * 如果元素滚动到底, 下面等式返回true, 没有则返回false:
           * ele.scrollHeight - ele.scrollTop === ele.clientHeight;
           */
          const condition = this.scrollHeight - this.scrollTop - 2 <= this.clientHeight
          if (condition) {
            binding.value()
          }
        })
      }
    }
  },
  props: {
    selectProps: {
      type: Object,
      default: () => {
        return {
          options: [],
          rangeNumber: 50
        }
      },
      require: true
    },
    dataIndex: {
      type: Number,
      default: 0
    },
    value: {
      type: String,
      default: ''
    }
  },
  data () {
    return {
      selectValue: '',
      rangeNumber: this.selectProps.rangeNumber || 50,
      options: [],
      originalData: [],
      query: ''
    }
  },
  watch: {
    value: {
      handler (newVal) {
        this.selectValue = newVal
      },
      deep: true,
      immediate: true
    },
    selectProps () {
      this.init()
    }
  },
  created () {
    this.delayFilter = _.debounce((query) => {
      this.filter(query)
    }, 500)
  },
  mounted () {
    this.$nextTick(() => {
      if (this.selectProps.options && this.selectProps.options.length > 0) {
        this.init()
      }
    })
  },
  methods: {
    init () {
      this.originalData = this.selectProps.options.concat()
      this.initRenderOpions(this.originalData)
    },
    loadMore (n) {
      if (n < 8) this.rangeNumber = 10
      this.rangeNumber += 5 // 每次滚动到底部可以新增条数  可自定义
      this.filter(this.query)
    },
    filter (query) {
      this.query = query
      if (this.query) {
        const newOption = this.originalData.filter((item) =>
          item[this.selectProps.label || 'label'].includes(query)
        )
        this.initRenderOpions(newOption)
      } else {
        this.initRenderOpions(this.originalData)
      }
    },
    selectChange () {
      this.$emit('updateChange', this.selectValue, this.dataIndex)
      this.initRenderOpions(this.originalData)
    },
    initRenderOpions (list) {
      const options = list.slice(0, this.rangeNumber)
      let index = -1
      if (_.size(this.selectValue)) {
        index = _.findIndex(options, (item) => {
          return item[this.selectProps.label || 'label'] === this.selectValue
        })
        if (index === -1) {
          const currentItem = _.find(list, (game) => {
            return game[this.selectProps.label || 'label'] === this.selectValue
          })
          if (currentItem) {
            options.unshift(currentItem)
          }
        }
      }
      this.options = options
    }
  }
}
</script>

 

posted on 2024-03-08 13:41  不愿透露名称的王先生  阅读(16)  评论(0编辑  收藏  举报

导航