选择器 Select
选择器的基本用法。通过 trigger-props 属性自定义下拉框的属性,比如可以让下拉框自动适应最小宽度。
设置 bordered="false" 开启无边框模式,常用于沉浸式使用。
通过设置 allow-clear ,显示清除按钮。
通过设置 allow-create ,让选择器可以创建选项中不存在的条目。
使用 fallback-option 自定义选项中不存在的值,默认会在输入框中展示不存在的选项值。可能用于选项还没有获取完,或者远程搜索时选项改变了。
自定义字段名
Section titled “自定义字段名”可以通过 field-names 属性自定义 options 中数据的格式,支持同时映射 value、label 和分组使用的 children 字段。
下拉菜单的页脚
Section titled “下拉菜单的页脚”自定义下拉菜单的页脚
使用 optgroup 组件添加分组选项。
下拉菜单的页头
Section titled “下拉菜单的页头”自定义下拉菜单的页头
自定义选择框展示内容
Section titled “自定义选择框展示内容”通过 #label 插槽可以自定义选择框展示内容。
展示联动选择框的实现方法。
选择框和下拉菜单显示加载中状态。
通过设置 multiple ,可以让选择器支持多选。此外通过 max-tag-count 可以设置最多显示的标签个数。
使用 search 事件进行远程搜索,并改变选项。
下拉菜单滚动
Section titled “下拉菜单滚动”可以通过 dropdown-scroll 监听下拉菜单的滚动事件。或者通过 dropdown-reach-bottom 监听下拉菜单滚动到底部的事件。
通过设置 allow-search ,可以让选择器支持对选项的搜索,配合 filter-option 可以自定义搜索。
选择框分为 mini、small、medium、large 四种尺寸。
当前示例同时展示了两种推荐写法:直接传空对象,观察 Select 默认补齐的固定 36px 行高;或者显式传 itemSize,让配置更直观。对于大多数下拉场景,只要提供弹层高度,默认固定高度模式就足够了。
通过 virtual-list-props 开启虚拟列表。Select 的下拉项当前默认按固定高度处理:如果你没有显式传 itemSize 或 minItemSize,组件会按 36px 选项高度补齐固定模式;如果要手动指定固定高度,请传 itemSize;只有显式传 minItemSize 时,才会切到动态高度模式。完整参数与迁移映射见 虚拟列表迁移指南。
从 Arco Design 迁移
Section titled “从 Arco Design 迁移”Select 在当前组件库里仍然保持 Arco Design Vue 的主要使用习惯,但实现已经完全收敛到本地的 Trigger、SelectView、表单联动和主题体系。迁移时建议把它当作“标签名和少量扩展约定不变、交互和主题链路切到本地组件库”的替换。
| Arco Design Vue | SD Design Vue | 说明 |
|---|---|---|
a-select | sd-select | 选择器主体 |
a-option | sd-option | 选项组件 |
a-optgroup | sd-optgroup | 选项分组 |
v-model / model-value | v-model / model-value | 受控写法保持一致 |
popup-visible | popup-visible | 下拉框显隐控制保持一致 |
:options | :options | 仍支持对象数组数据源 |
field-names | field-names | 仍支持映射 value / label / children |
#label / #option / #header / #footer | 同名插槽 | 常见模板插槽可以直接迁移 |
- 迁移后的下拉层、弹出容器、表单联动和主题注入都复用当前组件库内部实现,所以涉及浮层挂载、局部主题和表单校验的场景,优先使用
popup-container、trigger-props和ConfigProvider,不要再额外包一层自定义 Teleport 或独立弹层。 - 当前版本不再对外暴露 render function 风格的自定义入口,选择框内容、多选标签和选项内容统一使用
label、tag、option插槽。旧业务如果有 JSX /h()风格的渲染函数,需要改成模板插槽。 max-tag-count="responsive"走的是当前组件库的响应式折叠策略:除非显式传0,否则会尽量保留至少一个可见标签,再把剩余数量折叠到+n。如果旧页面依赖“宽度不够时全部折叠”的表现,迁移后要重新验收。allow-clear在当前组件里默认就是开启的;如果旧业务显式依赖不可清空,迁移时要补上:allow-clear="false",不要假设默认行为和历史版本完全一致。
迁移前后示例
Section titled “迁移前后示例”<template> <a-select v-model="city" :style="{ width: '320px' }" placeholder="Please select ..."> <a-option value="beijing">Beijing</a-option> <a-option value="shanghai">Shanghai</a-option> </a-select></template><template> <sd-select v-model="city" :style="{ width: '320px' }" placeholder="Please select ..."> <sd-option value="beijing">Beijing</sd-option> <sd-option value="shanghai">Shanghai</sd-option> </sd-select></template>options + field-names
Section titled “options + field-names”<template> <a-select v-model="city" :options="options" :field-names="{ value: 'id', label: 'name' }" :style="{ width: '320px' }" /></template><template> <sd-select v-model="city" :options="options" :field-names="{ value: 'id', label: 'name' }" :style="{ width: '320px' }" /></template>自定义选中展示
Section titled “自定义选中展示”<template> <a-select default-value="beijing" :style="{ width: '320px' }"> <template #label="{ data }"> <span>{{ data?.label }} city</span> </template> <a-option value="beijing">Beijing</a-option> <a-option value="shanghai">Shanghai</a-option> </a-select></template><template> <sd-select default-value="beijing" :style="{ width: '320px' }"> <template #label="{ data }"> <span>{{ data?.label }} city</span> </template> <sd-option value="beijing">Beijing</sd-option> <sd-option value="shanghai">Shanghai</sd-option> </sd-select></template>建议的迁移顺序
Section titled “建议的迁移顺序”- 先替换组件标签:
a-select、a-option、a-optgroup分别替换为sd-select、sd-option、sd-optgroup,先保证页面能渲染。 - 再迁移数据写法:如果原来已经使用
options/field-names,通常可以原样保留;如果历史代码混用了插槽选项和对象数组,建议先统一成一种。 - 接着处理自定义展示:把旧的渲染函数或外层包装逻辑收敛到
label、tag、option、header、footer等插槽。 - 最后验收交互细节:重点检查远程搜索、多选折叠、浮层宽度、自定义挂载容器、表单校验和局部主题,确认它们已经切到当前组件库的行为链路。
从 Naive UI 迁移
Section titled “从 Naive UI 迁移”Select 也保留了一部分 Naive UI 迁移所需的兼容面,重点是受控写法和弹层显隐别名;但整体交互仍然以当前组件库的 Trigger、SelectView、插槽体系和主题体系为准。迁移时建议优先完成组件替换,再把 Naive 风格命名逐步收敛回本地 API。
| Naive UI | SD Design Vue | 说明 |
|---|---|---|
n-select | sd-select | 选择器主体 |
v-model:value | v-model:value / v-model | 当前同时支持 Naive 风格和本地默认写法 |
show / default-show | popup-visible / default-popup-visible,同时兼容 show / defaultShow | 建议逐步迁回本地命名 |
options | options | 对象数组数据源可直接保留 |
field-names | field-names | 仍支持字段映射 |
multiple | multiple | 多选模式写法保持一致 |
max-tag-count | max-tag-count | 仍支持数字和 responsive |
clearable | allow-clear | 需要改为本地命名 |
filterable | allow-search | 需要改为本地命名 |
render-tag / render-label | #tag / #label | 对外 render function 已移除,统一改用插槽 |
- 当前版本只兼容 Naive 中最常用的受控别名,比如
value、show、defaultShow。像filterable、clearable这类语义型属性没有保留同名别名,迁移时要主动改成allow-search、allow-clear。 - 对外 render function 已经移除,原来依赖
render-tag、render-label、选项 render 回调的场景,需要改成tag、label、option插槽。 - 多选标签折叠走的是当前组件库的本地响应式策略,
max-tag-count="responsive"会尽量至少保留一个标签可见,再折叠剩余数量;如果旧页面依赖 Naive 的宽度收缩细节,需要单独回归。 - 弹层、滚动定位、局部主题和表单联动都接到本地实现了,所以迁移后不要继续依赖 Naive 私有 DOM、类名或外层包裹的额外定位逻辑。
迁移前后示例
Section titled “迁移前后示例”<template> <n-select v-model:value="city" :options="options" /></template><template> <sd-select v-model:value="city" :options="options" /></template><template> <n-select v-model:value="city" :options="options" filterable clearable /></template><template> <sd-select v-model="city" :options="options" allow-search allow-clear /></template>render-tag 迁移到插槽
Section titled “render-tag 迁移到插槽”<template> <n-select v-model:value="value" multiple :options="options" :render-tag="renderTag" /></template><template> <sd-select v-model="value" multiple :options="options"> <template #tag="{ data }"> <span>{{ data?.label }}</span> </template> </sd-select></template>建议的迁移顺序
Section titled “建议的迁移顺序”- 先把
n-select替换成sd-select,保留原有options、v-model:value等低成本兼容写法,让页面先恢复可用。 - 再统一属性命名:把
filterable、clearable、show、default-show分别改成allow-search、allow-clear、popup-visible、default-popup-visible。 - 接着迁移自定义渲染:把
render-tag、render-label一类函数式扩展收敛成tag、label、option插槽。 - 最后回归交互细节:重点看多选标签折叠、远程搜索、清空按钮、弹层容器和表单联动,确认它们已经符合当前组件库的本地行为。
<select> Props
Section titled “<select> Props”| 参数名 | 描述 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| multiple | 是否开启多选模式(多选模式默认开启搜索) | boolean | false | |
| value (v-model:value) | 绑定值,兼容 Naive 风格双向绑定 | string| number| boolean| Record<string, unknown>| (string | number | boolean | Record<string, unknown>)[] | null | - | |
| model-value (v-model) | 绑定值 | string| number| boolean| Record<string, unknown>| (string | number | boolean | Record<string, unknown>)[] | null | - | |
| default-value | 默认值(非受控模式) | string| number| boolean| Record<string, unknown>| (string | number | boolean | Record<string, unknown>)[] | '' | [] | |
| input-value (v-model) | 输入框的值 | string | - | |
| default-input-value | 输入框的默认值(非受控模式) | string | '' | |
| size | 选择框的大小 | 'mini' | 'small' | 'medium' | 'large' | 'medium' | |
| placeholder | 占位符 | string | - | |
| loading | 是否为加载中状态 | boolean | false | |
| disabled | 是否禁用 | boolean | false | |
| error | 是否为错误状态 | boolean | false | |
| allow-clear | 是否允许清空 | boolean | true | |
| allow-search | 是否允许搜索 | boolean | { retainInputValue?: boolean } | true | |
| allow-create | 是否允许创建 | boolean | false | |
| max-tag-count | 多选模式下,最多显示的标签数量。responsive 会自动收敛为组件当前支持的展示模式 | number | 'responsive' | 'responsive' | |
| popup-container | 弹出框的挂载容器 | string | HTMLElement | - | |
| bordered | 是否显示输入框的边框 | boolean | true | |
| default-active-first-option | 是否在无值时默认选择第一个选项 | boolean | true | 2.43.0 |
| popup-visible (v-model) | 是否显示下拉菜单 | boolean | - | |
| default-popup-visible | 弹出框默认是否可见(非受控模式) | boolean | false | |
| unmount-on-close | 是否在下拉菜单关闭时销毁元素 | boolean | false | |
| filter-option | 是否过滤选项 | boolean | ((inputValue: string, option: SelectOptionData) => boolean) | true | |
| options | 选项数据 | (string | number | boolean | SelectOptionData | SelectOptionGroup)[] | [] | |
| virtual-list-props | 传递虚拟列表属性,传入此参数以开启虚拟滚动。迁移说明与完整参数 | VirtualListProps | - | |
| trigger-props | 下拉菜单的触发器属性 | TriggerProps | - | |
| fallback-option | 自定义值中不存在的选项 | boolean| (( value: string | number | boolean | Record<string, unknown> ) => SelectOptionData) | true | 2.10.0 |
| show-extra-options | 是否在下拉菜单中显示额外选项 | boolean | true | 2.10.0 |
| value-key | 用于确定选项键值的属性名 | string | 'value' | 2.18.0 |
| search-delay | 触发搜索事件的延迟时间 | number | 500 | 2.18.0 |
| limit | 多选时最多的选择个数 | number | 0 | 2.18.0 |
| field-names | 自定义 SelectOptionData 中的字段 | SelectFieldNames | - | 2.22.0 |
| scrollbar | 是否开启虚拟滚动条 | boolean | ScrollbarProps | true | 2.38.0 |
| show-header-on-empty | 空状态时是否显示header | boolean | false | |
| show-footer-on-empty | 空状态时是否显示footer | boolean | false | |
| tag-nowrap | 标签内容不换行 | boolean | false | 2.56.1 |
<select> Events
Section titled “<select> Events”| 事件名 | 描述 | 参数 | 版本 |
|---|---|---|---|
| change | 值发生改变时触发 | value: string | number | boolean | Record<string, unknown> | (string | number | boolean | Record<string, unknown>)[] | null | |
| input-value-change | 输入框的值发生改变时触发 | inputValue: string | |
| popup-visible-change | 下拉框的显示状态改变时触发 | visible: boolean | |
| clear | 点击清除按钮时触发 | - | |
| remove | 点击标签的删除按钮时触发 | removed: string | number | boolean | Record<string, unknown> | undefined | |
| search | 用户搜索时触发 | inputValue: string | |
| dropdown-scroll | 下拉菜单发生滚动时触发 | - | |
| dropdown-reach-bottom | 下拉菜单滚动到底部时触发 | - | |
| exceed-limit | 多选超出限制时触发 | value: string | number | boolean | Record<string, unknown> | undefinedev: Event | 2.18.0 |
<select> Slots
Section titled “<select> Slots”| 插槽名 | 描述 | 参数 | 版本 |
|---|---|---|---|
| trigger | 自定义触发元素 | - | 2.22.0 |
| prefix | 前缀元素 | - | 2.22.0 |
| search-icon | 选择框的搜索图标 | - | 2.16.0 |
| loading-icon | 选择框的加载中图标 | - | 2.16.0 |
| arrow-icon | 选择框的箭头图标 | - | 2.16.0 |
| footer | 下拉框的页脚 | - | |
| header | 下拉框的页头 | - | 2.43.0 |
| label | 选择框的显示内容 | data: SelectOptionData | |
| tag | 多选标签的显示内容 | data: SelectOptionData | |
| option | 选项内容 | data: SelectOptionData | |
| empty | 选项为空时的显示内容 | - |
<option> Props
Section titled “<option> Props”| 参数名 | 描述 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| value | 选项值(如不填,会从内容中获取) | string|number|boolean|object | - | |
| label | 选项标签(如不填,会从内容中获取) | string | - | |
| disabled | 是否禁用 | boolean | false | |
| tag-props | 展示的标签属性 | TagProps | - | 2.8.0 |
| extra | 额外数据。2.18.0 版本废弃,可使用对象形式的 value 扩展数据 | object | - | 2.10.0 |
| index | 用于手动指定选项的 index | number | - | 2.20.0 |
<optgroup> Props
Section titled “<optgroup> Props”| 参数名 | 描述 | 类型 | 默认值 |
|---|---|---|---|
| label | 选项组的标题 | string | - |
<optgroup> Slots
Section titled “<optgroup> Slots”| 插槽名 | 描述 | 参数 | 版本 |
|---|---|---|---|
| label | 选项组的标题 | - | 2.10.0 |
/** * @zh 选项 * @en Option */type Option = string | number | SelectOptionData | SelectOptionGroup;
/** * @zh 筛选 * @en Filter */type FilterOption = boolean | ((inputValue: string, option: SelectOptionData) => boolean);SelectOptionData
Section titled “SelectOptionData”| 参数名 | 描述 | 类型 | 默认值 |
|---|---|---|---|
| value | 选项值 | string | number | boolean | Record<string, unknown> | - |
| label | 选项内容 | string | - |
| disabled | 是否禁用 | boolean | false |
| tagProps | 选项对应的多选标签的属性 | Record<string, unknown> | - |
SelectOptionGroup
Section titled “SelectOptionGroup”| 参数名 | 描述 | 类型 | 默认值 |
|---|---|---|---|
| isGroup | 是否为选项组 | true | - |
| label | 选项组标题 | string | - |
| options | 选项组中的选项 | SelectOption[] | - |
VirtualListProps
Section titled “VirtualListProps”| 参数名 | 描述 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| items | 列表数据 | unknown[] | [] | |
| keyField | 用于提取每项唯一键,支持字段名或函数 | string | ((item, index) => string | number) | 'key' | |
| itemSize | 固定高度模式的 item 高度,传入后使用 RecycleScroller | number | string | ((item, index) => number) | - | |
| minItemSize | 动态高度模式的最小 item 高度;未传 itemSize 时使用 DynamicScroller | number | string | 32 | |
| buffer | 额外渲染缓冲区(像素) | number | 200 |
其余参数与暴露方法请查看 虚拟列表迁移指南。
使用 Object 格式作为选项的值
Section titled “使用 Object 格式作为选项的值”当使用 Object 格式作为选项的值时,需要通过 value-key 属性为选择器指定获取唯一标识的字段名,默认值为 value. 此外 value 的对象值需要在 setup 中定义好,不能够在模版中创建对象,这样会导致 Option 组件的重复渲染。
例如当我需要指定 key 为唯一标识时:
<template> <sd-select v-model="value" :style="{ width: '320px' }" placeholder="Please select ..." value-key="key" > <sd-option v-for="item of data" :value="item" :label="item.label" /> </sd-select></template>
<script> import { ref } from 'vue';
export default { setup() { const value = ref(); const data = [ { value: 'beijing', label: 'Beijing', key: 'extra1', }, { value: 'shanghai', label: 'Shanghai', key: 'extra2', }, { value: 'guangzhou', label: 'Guangzhou', key: 'extra3', }, { value: 'chengdu', label: 'Chengdu', key: 'extra4', }, ];
return { value, data, }; }, };</script>滚动容器中的下拉菜单分离问题
Section titled “滚动容器中的下拉菜单分离问题”Select 组件默认没有开启容器滚动的事件监听功能,如果遇到在滚动容器中下拉菜单分离的问题,可以手动开启内部 Trigger 组件的 updateAtScroll 功能。如果是在全局环境中存在此种情况,可以使用 ConfigProvider 组件默认开启此属性。
<sd-select :trigger-props="{ updateAtScroll: true }"></sd-select>