UseElSelect - 选择器
组件介绍
UseElSelect 是基于 Element Plus 的 ElSelect/ElSelectV2 二次封装的选择器组件,专注于解决原生选择器类型不匹配、Label 手动获取、多选格式转换、弹层层级遮挡等常见痛点,同时支持全局字典配置、纯文本渲染模式,完整兼容原生选择器核心属性,可直接替换原生 ElSelect/ElSelectV2 使用,大幅降低选择器场景的重复开发成本。
核心能力
- 双版本选择器智能切换
默认使用性能更优的 ElSelectV2 虚拟滚动选择器,支持大数据量选项流畅渲染;可通过 useV2 配置一键切换为旧版 ElSelect,兼容需要分组、自定义选项模板等特殊场景,无需修改业务代码即可适配不同版本选择器特性。
- 智能类型自动适配
内置类型统一处理逻辑,自动将 options 中所有选项的 value 值转换为 String 类型,同时对绑定的 modelValue 做自动类型兼容:数组值自动批量转 String、非字符串值自动转 String,彻底解决后端返回数字类型 value 与前端绑定值类型不匹配导致的「选项无法选中」「回显异常」等经典问题。
- Label 值自动同步更新
选择选项后自动同步触发 update:label 事件,单选场景返回选中项的文本内容,多选场景返回选中项文本数组,无需业务侧手动遍历 options 查找对应 label,直接通过 v-model:label 即可双向绑定获取选中文本,大幅简化表单提交、详情展示等场景的代码量。
- 多选格式灵活转换
支持 toJoin 配置项,开启后多选场景自动将选中值数组转换为逗号分隔的字符串,完美适配后端要求逗号拼接字符串传参的接口规范;反向绑定逗号分隔字符串时,组件内部自动解析为数组供选择器使用,业务侧无需额外做格式转换处理。
- 全局字典配置兼容
自动读取全局 finalDictProps 字典配置,默认适配 { value: 'value', label: 'label', children: 'children' } 标准字段结构,支持组件传入 dictProps 局部覆盖全局配置,灵活适配不同接口返回的字段名(如 id/name、code/title 等),无需在每个选择器中重复配置字段映射。
- 纯文本渲染模式支持
支持 useRender 配置开启纯文本渲染模式,在详情页、表格列等不需要下拉选择的场景,直接渲染选中的文本内容,无需额外编写 v-if 判断展示文本还是选择器;支持传入对象配置自定义渲染的 class 和 style,适配不同展示场景的样式需求。
- 弹层层级问题修复
内置 popper-style 配置,将下拉弹框 z-index 设置为 99999,彻底解决在 el-drawer、el-dialog 等高层级弹层组件中使用选择器时,下拉框被父级弹层遮挡的问题,无需业务侧手动调整层级样式。
- 键盘交互Bug修复
内置键盘事件处理逻辑,解决 Element Plus 原生选择器「选择选项后按回车键会重复弹出下拉框」的交互Bug,选择完成后按回车键不会意外触发下拉,提升表单填写的键盘操作体验。
- 原生选择器完全兼容
基于 Element Plus 选择器封装,完整支持 $attrs 透传,所有原生 ElSelect/ElSelectV2 的属性(如 multiple、filterable、disabled、size 等)和事件都可以直接使用,插槽完全兼容,可直接替换项目中原生选择器使用,无迁移成本。
- 开箱即用的默认配置
内置合理的默认配置:默认开启可清空(clearable: true)、默认占位符为「请选择」、默认宽度 100% 自适应容器,无需在每个选择器中重复配置这些常用属性,业务侧只需传入 options 和 v-model 即可快速使用。
- 安全的生命周期管理
组件挂载时自动绑定键盘事件监听,卸载时自动移除全局事件监听,避免事件残留导致的内存泄漏和交互异常,保证组件在动态渲染、v-if 切换等场景下的稳定性。
使用
Props
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
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
}