实现el-select下拉懒加载(自用)

 

<template v-slot>
  <el-select
    ref="selectLazyLoad"
    v-model="currentFieldInfo"
    v-selectLazyLoad:pageNum="loadMoreData(pageNum)"
    class="w-100"
    :loading="loading"
    filterable
    :multiple="fieldInfo.fieldType === 'multipleSelection'"
    clearable
    remote
    :remote-method="onSearch"
    :placeholder="fieldInfo.fieldName"
    empty-text="暂无数据"
    no-data-text="无匹配数据"
    no-match-text="无匹配数据"
    @visible-change="onChangeVisible"
    @clear="clearSelect"
    @focus="focusSelect"
  >
    <el-option v-for="item in fieldOptions" :key="item.value" :label="item.label" :value="item.value" />
  </el-select>
</template>

<script>
import Vue from 'vue'
import { getOptPageList } from '@/api/problemManage/problemManage.js'
import { throttleFirstExt } from '@/utils/common'
export default {
  name: 'SelectLazyLoad',
  props: {
    fieldInfo: {
      type: Object,
      default: () => { }
    },
    fieldValue: {
      type: Object,
      default: () => { }
    },
    categoryCode: {// 分类编码(问题分类编码、工单分类编码)
      type: String,
      default: () => ''
    }
  },
  data() {
    return {
      fieldOptions: [],
      pageNum: 1,
      currentFieldInfo: '',
      allowSearchFlag: true, // 是否允许检索, 防止连续输入时未组装好数据就再次检索
      page: {
        // 查询后端所用参数对象, 可根据自己需求变更请求参数对象
        page: 1,
        limit: 20
      },
      queryParam: {
        factoryId: '',
        fieldCode: '',
        fieldValue: '',
        param: {
          code: ''
        }
      },
      inputValue: '',
      loading: false,
      noMoreData: false
    }
  },
  computed: {
    getFieldInfo() {
      // 父组件用来筛选fieldCode
      return this.fieldInfo
    }
  },
  watch: {
    currentFieldInfo: {
      // 选中数据改变时,调用父组件的setBranchNumber方法,并传入选中的值
      handler(val) {
        if (val) {
          this.$emit('update:fieldValueInfo', this.currentFieldInfo)
          this.$emit('setFieldInfo')
        } else {
          this.$emit('update:fieldValueInfo', '')
          this.$emit('setFieldInfo')
        }
      }
    },
    pageNum: {
      // 当前页数改变时, 重新触发查询
      handler(val) {
        if (val) {
          this.page.page = val
          this.queryBranchData('', true)
        }
      }
    }
  },
  created() {
    // 组件实例创建后(data和methods已经初始化完毕), 请求后端数据
    this.queryBranchData()
    this.selectLazyLoad()
  },
  mounted() {
    // 为了使父组件获取到fieldIndex属性
    this.$emit('setFieldInfo')
    // 添加下拉图标
    const rulesDom = this.$refs['selectLazyLoad'].$el.querySelector(
      '.el-input .el-input__suffix .el-input__suffix-inner .el-input__icon'
    ) // 找到dom
    rulesDom.classList.add('el-icon-arrow-up')
  },
  methods: {
    loadMoreData() {
      // 数据到底部继续滑动,会自动触发页数+1
      return () => {
        this.pageNum += 1
      }
    },
    onSearch(val) {
      // 检索功能, 后端可以支持模糊检索
      this.fieldOptions = []
      if (
        this.fieldInfo.fieldType === 'radioSelection' &&
        val &&
        this.$refs.selectLazyLoad.selectedLabel === val
      ) {
        if (this.allowSearchFlag && val.length > 0) {
          // 输入超过两个字符进行检索
          // this.allowSearchFlag = false;
          this.pageNum = 1
          this.queryParam.fieldValue = val
          this.queryBranchData()
        }
      } else if (this.fieldInfo.fieldType === 'multipleSelection' && val) {
        this.pageNum = 1
        this.queryParam.fieldValue = val
        this.queryBranchData()
      } else {
        this.initData()
      }
    },
    queryBranchData: throttleFirstExt(function(param, appendFlag) {
      if (
        this.fieldInfo.fieldType === 'radioSelection' &&
        this.$refs.selectLazyLoad &&
        this.$refs.selectLazyLoad.selectedLabel !== this.queryParam.fieldValue
      ) {
        this.queryParam.fieldValue = ''
      }
      this.queryParam.fieldCode = this.fieldInfo.fieldCode
      this.queryParam.param.code = this.categoryCode

      if (!this.noMoreData) {
        getOptPageList(this.queryParam, this.page).then((response) => {
          this.noMoreData = !response.data.data.length
          response.data.data.forEach((item) => {
            this.fieldOptions.push({
              label: item.fieldValue,
              value: item.fieldValue
            })
          })
        })
      }
    }, 200),
    initData() {
      this.noMoreData = false
      this.pageNum = 1
      this.queryParam.fieldValue = ''
      this.fieldOptions = []
      this.queryBranchData()
    },
    clearSelect() {
      // 清空下拉框选中的值,会向后端重新查询第一页的数据
      this.initData()
    },
    focusSelect() {
      // 光标触发下拉框时,如果下拉框数据为空,则向后端查询第一页数据
      if (this.fieldOptions.join() === '') {
        this.initData()
      }
    },
    onChangeVisible(val) {
      if (val) {
        this.initData()
      } else {
        this.noMoreData = false
        this.pageNum = 1
        this.queryParam.fieldValue = ''
        this.fieldOptions = []
      }
      const rulesDom = this.$refs['selectLazyLoad'].$el.querySelector(
        '.el-input .el-input__suffix .el-input__suffix-inner .el-input__icon'
      ) // 找到dom
      if (val) {
        rulesDom.classList.add('is-reverse') // 对dom新增class
      } else {
        rulesDom.classList.remove('is-reverse') // 对dom新增class
      }
    },
    getFactoryId(factoryId) {
      this.queryParam.factoryId = factoryId
    },
    selectLazyLoad() {
      // el-select组件数据过多,使用翻页加载数据指令
      Vue.directive('selectLazyLoad', {
        bind(el, binding) {
          const SELECT_WRAP_DOM = el.querySelector(
            '.el-select-dropdown .el-select-dropdown__wrap'
          )
          SELECT_WRAP_DOM.addEventListener('scroll', function() {
            // toFixed:把this.scrollTop转换为整数,兼容不同版本浏览器
            const condition =
              this.scrollHeight - this.scrollTop <= this.clientHeight
            if (condition) binding.value()
          })
        }
      })
    },
    // 父组件调用回显fieldValue
    echoData(fieldInfo) {
      if (fieldInfo.fieldValue) {
        this.currentFieldInfo = fieldInfo.fieldValue
      } else {
        this.currentFieldInfo = null
      }
    }
  }
}
</script>

<style scoped>
.w-100 {
  width: 100%;
}
</style>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值