FilterSelect.vue

<template>
  <el-select
    v-model="innerValue"
    :disabled="disabled"
    filterable
    clearable
    :placeholder="placeholder"
    :filter-method="handleFilter"
    @change="changeHandler"
  >
    <el-option
      v-for="item in options"
      :key="item[keyField]"
      :label="item[labelField]"
      :value="item[valueField]"
    />
  </el-select>
</template>
<script>
export default {
  name: 'FilterSelect',
  model: {
    // model选项可以自定义prop名称和event名称
    prop: 'value',
    event: 'handleSelectChange'
  },
  props: {
    // 下拉框数据
    value: {
      type: String,
      default: () => ''
    },
    selectList: {
      type: Array,
      default: () => []
    },
    disabled: {
      type: Boolean,
      default: () => false
    },
    placeholder: {
      type: String,
      default: () => '请选择'
    },
    labelField: {
      type: String,
      default: () => 'label'
    },
    valueField: {
      type: String,
      default: () => 'value'
    },
    keyField: {
      type: String,
      default: () => 'key'
    }
  },
  data() {
    return {
      //  下拉框实际渲染的数据
      options: [],
      innerValue: ''
    }
  },
  watch: {
    value(val) {
      // 将value同步到innerValue
      this.innerValue = val
    },

    options(val) {
      // 回显功能
      if (
        val.length > 0 &&
        this.selectList.length > 0 &&
        this.valueField &&
        this.value
      ) {
        const optionIsContain = val.filter(
          (item) => item[this.valueField] === this.value
        )
        if (optionIsContain.length === 0) {
          const activeItem = this.selectList.filter(
            (item) => item[this.valueField] === this.value
          )[0]
          this.options.unshift(activeItem)
        }
      }
      // 长度控制
      if (val.length > 30) {
        this.options = val.slice(0, 30)
      }
    },
    'selectList.length': function(n, o) {
      if (n !== o) {
        this._initData()
      }
    }
  },
  mounted() {
    this._initData()
  },
  methods: {
    // 初始化数据
    _initData() {
      this.options =
        this.selectList.length <= 30
          ? this.selectList
          : this.selectList.slice(0, 30)
      // 初始化选中值
      this.innerValue = this.value
    },
    // v-model关键函数
    changeHandler(val) {
      this.$emit('handleSelectChange', val)
    },
    // 搜索函数
    handleFilter(query) {
      if (query !== '') {
        this.options = this.selectList
          .filter((item) => {
            return (
              item[this.labelField].toLowerCase().indexOf(query.toLowerCase()) >
              -1
            )
          })
          .slice(0, 30)
      } else {
        this.options =
          this.selectList.length > 30
            ? this.selectList
            : this.selectList.slice(0, 30)
      }
    }
  }
}
</script>

📦 前端资源合集 | 持续更新

🟢 前端0到1【持续更新】→ https://pan.quark.cn/s/5df55ccff7c4

🔵 前端进阶【持续更新】→ https://pan.quark.cn/s/2dec1c87b3ec

🟣 前端2026最新【持续更新】→ https://pan.quark.cn/s/77c8fa94161c

🔴 AI最新学习资料 → https://pan.baidu.com/s/1P9X2Qk_Fby3rFNVGw_WKow?pwd=46XG 提取码:46XG

觉得有用就点个赞+收藏,关注我持续分享前端干货 💡

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐