Skip to content

UseElSelect - 选择器

组件介绍

UseElSelect 是基于 Element Plus 的 ElSelect/ElSelectV2 二次封装的选择器组件,专注于解决原生选择器类型不匹配、Label 手动获取、多选格式转换、弹层层级遮挡等常见痛点,同时支持全局字典配置、纯文本渲染模式,完整兼容原生选择器核心属性,可直接替换原生 ElSelect/ElSelectV2 使用,大幅降低选择器场景的重复开发成本。

核心能力

  1. 双版本选择器智能切换

默认使用性能更优的 ElSelectV2 虚拟滚动选择器,支持大数据量选项流畅渲染;可通过 useV2 配置一键切换为旧版 ElSelect,兼容需要分组、自定义选项模板等特殊场景,无需修改业务代码即可适配不同版本选择器特性。

  1. 智能类型自动适配

内置类型统一处理逻辑,自动将 options 中所有选项的 value 值转换为 String 类型,同时对绑定的 modelValue 做自动类型兼容:数组值自动批量转 String、非字符串值自动转 String,彻底解决后端返回数字类型 value 与前端绑定值类型不匹配导致的「选项无法选中」「回显异常」等经典问题。

  1. Label 值自动同步更新

选择选项后自动同步触发 update:label 事件,单选场景返回选中项的文本内容,多选场景返回选中项文本数组,无需业务侧手动遍历 options 查找对应 label,直接通过 v-model:label 即可双向绑定获取选中文本,大幅简化表单提交、详情展示等场景的代码量。

  1. 多选格式灵活转换

支持 toJoin 配置项,开启后多选场景自动将选中值数组转换为逗号分隔的字符串,完美适配后端要求逗号拼接字符串传参的接口规范;反向绑定逗号分隔字符串时,组件内部自动解析为数组供选择器使用,业务侧无需额外做格式转换处理。

  1. 全局字典配置兼容

自动读取全局 finalDictProps 字典配置,默认适配 { value: 'value', label: 'label', children: 'children' } 标准字段结构,支持组件传入 dictProps 局部覆盖全局配置,灵活适配不同接口返回的字段名(如 id/name、code/title 等),无需在每个选择器中重复配置字段映射。

  1. 纯文本渲染模式支持

支持 useRender 配置开启纯文本渲染模式,在详情页、表格列等不需要下拉选择的场景,直接渲染选中的文本内容,无需额外编写 v-if 判断展示文本还是选择器;支持传入对象配置自定义渲染的 class 和 style,适配不同展示场景的样式需求。

  1. 弹层层级问题修复

内置 popper-style 配置,将下拉弹框 z-index 设置为 99999,彻底解决在 el-drawer、el-dialog 等高层级弹层组件中使用选择器时,下拉框被父级弹层遮挡的问题,无需业务侧手动调整层级样式。

  1. 键盘交互Bug修复

内置键盘事件处理逻辑,解决 Element Plus 原生选择器「选择选项后按回车键会重复弹出下拉框」的交互Bug,选择完成后按回车键不会意外触发下拉,提升表单填写的键盘操作体验。

  1. 原生选择器完全兼容

基于 Element Plus 选择器封装,完整支持 $attrs 透传,所有原生 ElSelect/ElSelectV2 的属性(如 multiple、filterable、disabled、size 等)和事件都可以直接使用,插槽完全兼容,可直接替换项目中原生选择器使用,无迁移成本。

  1. 开箱即用的默认配置

内置合理的默认配置:默认开启可清空(clearable: true)、默认占位符为「请选择」、默认宽度 100% 自适应容器,无需在每个选择器中重复配置这些常用属性,业务侧只需传入 options 和 v-model 即可快速使用。

  1. 安全的生命周期管理

组件挂载时自动绑定键盘事件监听,卸载时自动移除全局事件监听,避免事件残留导致的内存泄漏和交互异常,保证组件在动态渲染、v-if 切换等场景下的稳定性。

使用

UseElSelect

Props

ts
import type { PropType } from 'vue'
import type { DictProps, RenderConfig } from '@/types'

/**
 * 组件props
 */
export default {
  /**
   * 双向绑定数据源
   */
  modelValue: {
    type: [String, Number, Boolean, Array],
    default: ''
  },
  /**
   * 选项数据源
   */
  options: {
    type: Array as PropType<Record<string, any>[]>,
    default: () => []
  },
  /**
   * 字典属性 默认为{ value: 'value', label: 'label', children: 'children' },可通过全局配置进行设置,为适配全局配置此处不再设置默认值
   */
  dictProps: {
    type: Object as PropType<DictProps>,
    default: () => ({})
  },
  /**
   * 是否使用渲染器 默认否
   */
  useRender: {
    type: [Boolean, Object] as PropType<boolean | RenderConfig>,
    default: false
  },
  /**
   * 是否使用v2版本 默认是
   */
  useV2: {
    type: Boolean,
    default: true
  },
  /**
   * 是否可清空 默认是
   */
  clearable: {
    type: Boolean,
    default: true
  },
  /**
   * 开启多选时是否将选中的数组转为以逗号分隔的字符串 默认否
   */
  toJoin: {
    type: Boolean,
    default: false
  },
  /**
   * placeholder 默认请选择
   */
  placeholder: {
    type: String,
    default: '请选择'
  },
  /**
   * 宽度,默认100%
   */
  width: {
    type: String,
    default: '100%'
  }
}

Types

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

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

/**
 * emits类型
 */
export type Emits = {
  /** 更新value值 */
  (e: 'update:modelValue', value: string | number | (string | number)[]): void
  /** 更新label值 */
  (e: 'update:label', label: string | string[]): void
}

基于 MIT 许可发布