element-ui-解决下拉框数据量过多问题(selectLoadmore)

vue-virtual-scroll-list与selectLoadmore对比:
vue-virtual-scroll-list:一次性返回所有数据。即数据量适中,几千到一两万条,可一次性被后台接口返回的情况下,建议使用vue-virtual-scroll-list。
selectLoadmore:可懒加载下拉框,数据量超级大,几万甚至十几万条以上,后台无法一次性返回,只能分页加载的情况下,建议使用selectLoadmore。
一、components/selectLoadmore/index.vue
<template>
    <el-select class="ba-content" :popper-append-to-body="false" 
      :value-key="valueName" 
      v-model="selectedOptions" 
      v-el-select-loadmore="loadmore" 
      @change="change" 
      :remote-method="remoteMethodThrottle" 
      :loading="loading" 
      @visible-change="visibleChange" clearable filterable remote 
      :placeholder="!disabled?'请输入关键词':'——'" :disabled="disabled">
      <el-option v-for="item in showList" :key="item[valueName]" :label="item[valueName]" :value="item"></el-option>
    </el-select>
</template>

<script>
export default {
  name: 'el-select-loadmore',
  props: {
    value: {
      type: String
    },
    showList: {
      type: Array
    },
    placeholder: {
      type: String
    },
    disabled: {
      type: Boolean,
      default: false
    },
    //相同名称的label和value不需传参给子组件,采用默认值
    valueName: {
      type: String,
      default: 'label'
    },
    labelName: {
      type: String,
      default: 'value'
    }
  },
  data() {
    return {
      //data重新定义变量接受组件v-model(value:名称必须为value)值,不改变props接收的值
      selectedOptions: this.value,
      loading: false
    }
  },
  //监听值的变化
  watch: {
    value(newVal) {
      this.selectedOptions = newVal
    }
    //若选择器的值发生改变,则传参给父组件
    //this.$emit(‘input’,val),在父组件直接用v-model绑定,则可以直接获取到
    // selectedOptions(newVal, oldVal) {
    // this.$emit('input', this.selectedOptions)
    // }
  },
  // 自定义指令(和method同级)
  directives: {
    // 下拉框懒加载(el-select-loadmore是自定义的指令,使用时前面加v-)
    'el-select-loadmore': {
      // el:使用自定义指令的元素(下拉框),
      bind(el, binding) {
        // 下拉框下拉的框
        const SELECTWRAP_DOM = el.querySelector(
          '.el-select-dropdown .el-select-dropdown__wrap'
        )
        // 增加滚动监听,
        SELECTWRAP_DOM.addEventListener('scroll', function () {
          // scrollHeight:当前所有选项的高度
          // scrollTop:滚动的距离
          // clientHeight:下拉框的高度
          // const condition =
          //   this.scrollHeight - this.scrollTop == this.clientHeight ||
          //   this.scrollHeight - this.scrollTop == this.clientHeight + 1
          const condition =
            this.scrollHeight - this.scrollTop <= this.clientHeight + 40
          // 当滚动条滚动到最底下的时候执行接口加载下一页
          if (condition) {
            binding.value()
          }
        })
      }
    }
  },
  computed: {
    // 防抖
    remoteMethodThrottle() {
      let time = null
      return (param) => {
        if (time) {
          clearTimeout(time)
        }
        time = setTimeout(() => {
          // 搜索方法
          this.remoteMethod(param)
          clearTimeout(time)
        }, 1000)
      }
    }
  },
  methods: {
    // 下拉框出现、隐藏
    visibleChange(val) {
      this.$emit('visibleChange', val)
    },
    // 自定义指令的方法:下拉框滚动到底懒加载
    loadmore() {
      this.$emit('loadmore')
    },
    // 远程搜索物料类别
    remoteMethod(query) {
      this.$emit('remoteMethod', query)
    },
    // 选择器的值发生改变
    change(item) {
      this.$emit('change', item)
    }
  }
}
</script>
<style lang="scss" scoped>
</style>
二、调用页面
<template>
        <selectLoadmore :disabled="disabled" :value="base.otpTcmDise" :showList="selectOptions" valueName="diagName" @loadmore="loadmore" @remoteMethod="remoteMethod" @visibleChange="visibleChange" @change="(val) => change(val, 'tcmDiseCode')"></selectLoadmore>
</template>
<script>
  data() {
    return {
      // 搜索,远程,懒加载下拉相关数据
      querys: '', // 远程搜索输入的内容
      selectLoading: false, //select加载
      stopLoading: false, // 最后一次加载之后,不再加载
      pageData: {
        // 懒加载相关参数,这里代表从第一条数据开始加载,一次加载十项
        current: 1,
        size: 10
      },
      selectOptions: [],
    }
  },
  methods: {
    // 下拉框出现、隐藏
    visibleChange(val) {
      if (!val) {
        //隐藏
        // 重置懒加载
        this.stopLoading = false
        // 重置数据
        this.querys = null
        this.pageData = {
          // 懒加载相关参数,这里代表从第一条数据开始加载,一次加载十项
          current: 1,
          size: 10
        }
        this.selectOptions = []
      }
    },
    // 自定义指令的方法:下拉框滚动到底懒加载
    loadmore() {
      if (!this.stopLoading) {
        this.pageData.current++ // 搜索下一页
        this.getTypeOption(this.pageData) //调用接口获取下拉框数据
      }
    },
    // 远程搜索物料类别
    remoteMethod(query) {
      this.querys = query // 保存搜索内容
      // 重置懒加载
      this.stopLoading = false
      this.pageData = {
        current: 1,
        size: 10
      }
      let params = this.pageData
      params.query = query
      // 调用接口
      this.selectLoading = true
      _interface(params).then((res) => {
        if (res.code == 200) {
          this.selectOptions = res.result.records
        } else {
          this.$message({ type: 'error', message: '错误返回提示' })
        }
        this.selectLoading = false
      })
    },
    // 获取物料类别下拉内容
    getTypeOption(params) {
      params.query = this.querys
      this.selectLoading = true
      _interface(params).then((res) => {
        if (res.code == 200) {
          // 如果某次返回值是[],表示已经加载完了,不必再加载
          if (res.result.records.length == 0) {
            this.stopLoading = true
            return
          }
          if (params.current == 1) {
            // 保存数据
            this.selectOptions = res.result.records
          } else {
            this.selectOptions = [...this.selectOptions, ...res.result.records]
          }
        } else {
          this.$message({ type: 'error', message: '错误返回提示' })
        }
        this.selectLoading = false
      })
    },
    // 西医
    change(obj, key) {
      this.base[key] = obj.diagCode
    }
  }
</script>

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值