Skip to content

UseElSelect - 选择器

组件介绍

UseElSelect 是基于 Element Plus 的el-select-v2el-select进行二次封装的通用选择器组件,旨在简化选择器的使用流程、统一交互逻辑、减少重复开发成本。该组件兼容el-select-v2(虚拟滚动版本)和原生el-select两种底层实现,支持单选 / 多选、自定义字段映射、选中值格式转换等核心能力,仅需通过配置项即可完成绝大部分选择器场景的开发,无需重复编写模板代码,大幅提升中后台系统中选择器的开发效率和可维护性。

核心亮点

  1. 双版本无缝兼容:同时支持 el-select-v2(虚拟滚动)和原生 el-select,通过 useV2 配置项一键切换,既满足大数据量场景下的性能需求(虚拟滚动),也适配小数据量的常规使用场景。
  2. 灵活的选中值格式适配:针对多选场景,支持通过 isJoin 配置将选中的数组自动转为逗号分隔的字符串,也可保留原生数组格式,适配不同后端接口的数据格式要求,无需手动处理格式转换。
  3. 极简的模板开发:无需重复编写 el-option 循环、el-select 基础属性绑定等模板代码,仅需传入数据源 options 和少量配置项,即可完成选择器渲染。
  4. 自定义字段映射:通过 defaultProps 配置项可灵活定义选项的 label 和 value 字段名,无需修改原始数据源结构,适配不同格式的选项列表。
  5. 自动类型适配:组件内置值类型自动转换逻辑,根据选项数据源的 value 字段类型,自动处理字符串 / 数字类型的选中值转换,避免类型不匹配导致的选中异常。

解决痛点

  1. 原生 el-select 重复模板代码过多
  • 痛点:每个选择器页面都需编写 el-select、el-option 循环标签,重复绑定 placeholder、style、@change 等属性,多选场景还需额外处理数组 / 字符串转换,开发效率低且易出错。
  • 解决方案:组件封装了所有基础模板和事件逻辑,模板中仅需引入<UseElSelect>并传入 options 等核心配置项,减少 90% 以上的重复模板代码,且配置项可统一维护、复用。
  1. 多选场景值格式处理逻辑不统一
  • 痛点:原生多选选择器返回的是数组格式,但部分后端接口要求逗号分隔的字符串,每个页面需手动编写 join()/split() 转换逻辑,不同开发者实现方式不同,易出现格式错误、逻辑不一致问题。
  • 解决方案:组件通过 isJoin 配置项统一处理多选值格式,开启后自动将选中数组转为逗号分隔字符串,关闭则保留数组格式,无需手动编写转换逻辑,格式处理规则全局统一。
  1. 选项字段名不统一,适配成本高
  • 痛点:不同业务场景的选项数据源字段名不一致(如有的是 name/id,有的是 label/value),使用原生 el-select 时需手动映射字段,修改数据源结构或在模板中重复编写 label="item.name" 等代码,适配成本高。
  • 解决方案:组件通过 defaultProps 配置项支持自定义 label/value 字段名,例如 defaultProps="{ label: 'name', value: 'id' }" 即可适配 name/id 格式的数据源,无需修改原始数据,适配逻辑统一且灵活。
  1. 虚拟滚动版本切换成本高
  • 痛点:原生 el-select 处理大数据量(万级以上选项)时性能差,需切换到 el-select-v2,但两者模板结构、属性绑定有差异,切换时需大幅修改模板代码,成本高且易引入新问题。
  • 解决方案:组件内置 useV2 配置项,一键切换 el-select-v2/el-select 底层实现,模板和配置项无需修改,大数据量场景仅需开启 useV2: true 即可享受虚拟滚动性能优化,切换成本几乎为 0。
  1. 选中值类型不匹配导致选中异常
  • 痛点:原生 el-select 不会自动处理选中值的类型(如选项 value 是数字类型,但传入的 modelValue 是字符串),导致选中状态不生效,每个页面需手动转换类型,易遗漏且排查困难。
  • 解决方案:组件内置 valueType 计算属性,自动识别选项 value 字段的类型,对传入的 modelValue 进行自动类型转换(如字符串数字转数字类型),避免因类型不匹配导致的选中异常,无需手动处理类型逻辑。
  1. 跨页面选择器样式 / 交互不一致
  • 痛点:中后台系统多个页面的选择器,因无统一封装,宽度、placeholder、选中事件处理逻辑等不一致,影响用户体验,且后期调整样式 / 交互需逐个页面修改,维护成本高。
  • 解决方案:组件内置统一的默认样式(如宽度默认 100%)、默认占位符(请选择)和统一的 change 事件处理逻辑,同时支持通过 width、placeholder 等配置项覆盖默认值,既保证全局样式 / 交互一致性,又满足个性化需求。

使用案例

Types

js
import type { ExtractPropTypes } from 'vue'
import componentProps from './props'

/**
 * props类型
 */
export type Props = ExtractPropTypes<typeof componentProps>

/**
 * emits接口
 */
export interface Emits {
  // 更新value值
  (e: 'update:modelValue', value: string | number | (string | number)[]): void
  // 更新label值
  (e: 'update:label', label: string | string[]): void
}

ComponentProps

js
import type { PropType } from 'vue'
import type { DictProps } from '@/types/dict'

/**
 * 组件props
 */
export default {
  /**
   * 双向绑定数据源
   */
  modelValue: {
    type: [String, Number, Array],
    default: ''
  },
  /**
   * 选项数据源
   */
  options: {
    type: Array as PropType<Record<string, any>[]>,
    default: () => []
  },
  /**
   * 是否使用v2版本 默认是
   */
  useV2: {
    type: Boolean,
    default: true
  },
  /**
   * 开启多选时是否将选中的数组转为以逗号分隔的字符串 默认否
   */
  isJoin: {
    type: Boolean,
    default: false
  },
  /**
   * placeholder 默认请选择
   */
  placeholder: {
    type: String,
    default: '请选择'
  },
  /**
   * 宽度,默认100%
   */
  width: {
    type: String,
    default: '100%'
  },
  /**
   * 选项默认配置
   */
  defaultProps: {
    type: Object as PropType<DictProps>,
    default: () => ({ label: 'label', value: 'value' })
  }
}

Props && Emits

js
const props = defineProps(componentProps)

const emits = defineEmits<Emits>()

基于 MIT 许可发布