element-ui封装的带模糊查询的下拉框

文章描述了一个Vue组件InfoSelect,它是一个支持单选的动态下拉选择器,可以处理多列选项,具有远程加载和数据绑定功能。组件还包含自定义事件如`change`、`toBottom`和`resetOptions`。
摘要由CSDN通过智能技术生成
<template>
  <div>
    <el-select 
      v-el-select-loadmore="deLoadMore" 
      v-show="isShowSelect" 
      v-model="selectedValue" 
      v-bind="$attrs"
      ref="oSelect" 
      @change="changeHandler" 
      @visible-change="visibleChange"
      :disabled="disabled"
      class="width100"
      :placeholder="placeholder"
      >

      <!-- 表头 -->
      <el-option
        v-if="selectOptions.length && labelParams.length > 1"
        disabled
        :key="new Date().getTime()"
        :value="new Date().getTime()"
      >
        <div class="header">
          <div
            v-for="(item, index) in headerLabel"
            :key="index"
            :style="`display: inline-block;width:${columnWidth[index]}`"
            :class="{ ml20: index != 0, option: true }"
          >
          {{ item }}
          </div>
        </div>
      </el-option>
      <!-- 选项,支持一列或多列,由labelParams的元素个数决定 -->
      <el-option 
        v-for="(item,index) in selectOptions" 
        :key="`opt-${index}`" 
        :value="isItemNotObj ? item : item[valueName]" 
        :label="isItemNotObj ? item : (item[defaultLabel] || item[labelParams[0]])"
      >
        <div class="header">
          <div
            v-for="(params, index) in labelParams"
            :key="index"
            :style="`display: inline-block;width:${columnWidth[index]}`"
            :class="{ ml20: index != 0, option: true }"
          >
          {{ isItemNotObj ? item : item[params] }}
          </div>
        </div>

      </el-option>
   

      <!-- <el-option 
        v-for="item in selectOptions" 
        :key="item[valueName]" 
        :value="item[valueName]" 
        :label="item[labelName]"
      >
      </el-option> -->

    </el-select>

    <el-input :placeholder="placeholder" v-show="!isShowSelect" v-model="inputLabel" @click.native="changeVisible" readonly :disabled="disabled"></el-input>
  </div>
</template>

<script>
import { debounce } from "@/utils/index.js"
export default {
  name: "InfoSelect",
  /**
   * !!!不支持多选
   */
  props: {
    placeholder:{
      default: '请选择',
      type: [String, Number]
    },
    //如果option数组的元素不是对象,将此项置为true。为true时不需传valueName和labelParams
    isItemNotObj:{
      default: false,
      type: Boolean
    },
    value: {
      // required: true,
      type: [String, Number]
    },
    //输入框显示值
    inputLabel: {
      default: ""
    },
    // 选项,option列表
    selectOptions: {
      type: Array,
      default: () => []
    },
    //option的value变量名
    valueName: {
      default: 'value'
    },
    // 设置每列宽度
    columnWidth: {
      type: Array,
      default: function (){
        return ['200px', '200px']
      }
    },
    // 表头显示文字(只有一列时不显示)
    headerLabel: {
      type: Array,
      default: () => [],
    },
    //每一列label的变量名(只有一列就输入一个元素)
    labelParams:{
      type: Array,
      default: () => ['label']
    },
    disabled:{
      type: Boolean,
      default: false
    },
    //选中某一项后,select中显示的字段,不传的话默认为labelParams的第一项
    defaultLabel:{
      default: ""
    }
  },
  data() {
    return {
      //是否正在展示select
      isShowSelect: false,
      // 触底事件
      deLoadMore: debounce(this.loadMore, 100)
    }
  },
  computed:{
    // el-select的v-model
    selectedValue:{
      get(){
        return this.value
      },
      set(newVal){
        this.$emit('input', newVal)
      }
    }
  },
  methods: {
    loadMore() {
      // 防止搜索结果太少时,触发“滚动条触底”事件
      if (this.selectOptions.length <= 6) return
      let input = this.$refs.oSelect.$children[0].$refs.input;
      let keyword = input.value
      //触底事件,抛出此时输入框的内容
      this.$emit('toBottom', keyword)
    },
    changeHandler(value) {
      let selectedObj = undefined
      if(!this.isItemNotObj){
        selectedObj = this.selectOptions.find(item => item[this.valueName] == value)
      }
      // 自定义事件抛出两个参数,第一个为选中的value值,第二个为选中value值所在的对象(清空选择时,selectedObj为undefined)
      this.$emit('changes', value, selectedObj)
      this.changeVisible()
    },
    //切换input和select
    changeVisible() {
      this.isShowSelect = !this.isShowSelect
      this.$nextTick(() => {
        if (this.isShowSelect) this.$refs.oSelect.focus()
      })
    },
    //下拉框出现/隐藏时触发, visible: 出现则为 true,隐藏则为 false
    visibleChange(visible){
      if(visible)return
      this.isShowSelect = false
    }
  },
  watch: {
    isShowSelect: {
      handler(newValue) {
        // 隐藏select时重置options
        if (newValue == false) this.$emit('resetOptions')
      }
    }
  },
  mounted() {
    
  }
}
</script>

<style scoped lang="scss">
.header {
  display: flex;
}
.option {
  display: inline-block;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
/deep/ .el-select-dropdown__list {
  padding-top: 0 !important;
}
.el-select-dropdown__item.is-disabled {
  background: #eff0f2;
}
</style>

父组件调用:

 <info-select
              v-model="formData.projectId"
              :inputLabel="formData.projectName"
              :selectOptions="projectList"
              @changes="projectSelChange"
              @toBottom="projectLoadMore"
              filterable
              remote
              :remote-method="projectRemoteMethod"
              @resetOptions="projectResetOptions"
              :disabled="isDisabled"
              :loading="projectRemoteLoading"
              placeholder="请选择项目名称"
              :columnWidth="['400px']"
             >
            </info-select>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SKMA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值