el-select懒加载封装

彭嘉赐
2023-12-01

组件代码:

<template>
  <div class="BaseSelect">
    <el-select v-option-sroll="loadmore" v-model="inputValue" filterable placeholder="请选择" ref="BaseSelect" @input.native="inputClick" value-key="id">
      <el-option v-for="item in dataList" :key="item.id" :label="item.name" :value="item"> </el-option>
    </el-select>
  </div>
</template>
<script>
import { Debounce } from '@/utils/Debounce.js'
export default {
  name: 'BaseSelect',
  directives: {
    'option-sroll': {
      bind(el, binding) {
        const SELECTWRAP_DOM = el.querySelector('.el-select-dropdown .el-select-dropdown__wrap')
        SELECTWRAP_DOM.addEventListener('scroll', function() {
          const condition = this.scrollHeight - this.scrollTop <= this.clientHeight
          if (condition) {
            binding.value()
          }
        })
      }
    }
  },
  data() {
    return {
      dataList: [], //下拉数据
      selectData: '',
      inputValue: '',
      debounce: Debounce(function() {
        //防抖
        if (this.isSearch) {
          this.filterData(this.$refs.BaseSelect.$data.selectedLabel)
        }
      }, 1600),
      // 数据长度
      dropDownDataLength: 0,
      // 懒加载长度
      loadStart: 0,
      loadEnd: 20,
      // 监听是否使用了搜索过滤
      isSearch: false,
      SearchValue: ''
    }
  },
  props: {
    // 远程搜索
    getDropDownData: {
      type: Function,
      require: false
    },
    // 下拉总数据
    dropDownData: {
      type: Array,
      require: true
    },
    // 搜索过滤条件
    filterConditions: {
      type: String,
      require: false
    }
  },
  created() {},
  mounted() {
    // this.getDropDownData() //使用组件传入一个过滤函数
  },
  watch: {
    dropDownData(val) {
      this.$nextTick(() => {
        this.dataList = this.dropDownData.slice(this.loadStart, this.loadEnd)
        this.dropDownDataLength = this.dropDownData.length
      })
    },
    SearchValue(val) {
      if (val !== '') {
        this.isSearch = true
        this.debounce()
      } else {
        this.isSearch = false
        this.reset()
      }
    },
    //下拉框的值
    inputValue(val) {
      this.$emit('selectValue', val)
    }
  },
  methods: {
    // 输入框发生改变搜索过滤选项
    filterData(value) {
      this.dataList = this.dropDownData.filter((item, index) => {
        if ((item.name !== null && item.name.indexOf(`${value}`) != -1) || this.inputValue == item.name) {
          return true
        }
      })
    },
    inputClick(val) {
      this.SearchValue = val.target.value // 获取输入框内容
    },
    // 下拉加载
    loadmore() {
      this.getUsers(this.formData)
    },
    getUsers(v) {
      if (this.isSearch) {
        if (this.loadEnd >= this.dropDownDataLength) {
          this.$message({
            type: 'info',
            message: '下拉选框已加载到底部'
          })
          return
        }
        return
      }
      // 如果还有数据未加载
      if (this.loadEnd + 20 <= this.dropDownDataLength) {
        this.loadStart += 20
        this.loadEnd += 20
      } else if (this.loadEnd + 20 > this.dropDownDataLength) {
        //无可加载数据
        this.loadStart += 20
        this.loadEnd += this.dropDownDataLength - this.loadEnd
      }
      this.dataList = this.dataList.concat(this.dropDownData.slice(this.loadStart, this.loadEnd))
    },
    // 重置下拉框
    reset() {
      this.loadStart = 0
      this.loadEnd = 20
      this.dataList = this.dropDownData.slice(this.loadStart, this.loadEnd)
    }
  }
}
</script>

使用组件:

//传入下拉数据 选中值返回selectValue事件
<BaseSelect :dropDownData="baseUserList" @selectValue="selectValue"></BaseSelect>

防抖:

export const Debounce = function(fn, delay) {
  var timer = null
  return function() {
    if (timer) {
      clearTimeout(timer)
    }
    timer = setTimeout(fn.bind(this), delay) //通过bind改变this指向 指向vue
  }
}
 类似资料: