跳转到内容

选择器 Select

选择器的基本用法。通过 trigger-props 属性自定义下拉框的属性,比如可以让下拉框自动适应最小宽度。

设置 bordered="false" 开启无边框模式,常用于沉浸式使用。

通过设置 allow-clear ,显示清除按钮。

通过设置 allow-create ,让选择器可以创建选项中不存在的条目。

使用 fallback-option 自定义选项中不存在的值,默认会在输入框中展示不存在的选项值。可能用于选项还没有获取完,或者远程搜索时选项改变了。

可以通过 field-names 属性自定义 options 中数据的格式,支持同时映射 valuelabel 和分组使用的 children 字段。

自定义下拉菜单的页脚

使用 optgroup 组件添加分组选项。

自定义下拉菜单的页头

通过 #label 插槽可以自定义选择框展示内容。

展示联动选择框的实现方法。

选择框和下拉菜单显示加载中状态。

通过设置 multiple ,可以让选择器支持多选。此外通过 max-tag-count 可以设置最多显示的标签个数。

使用 search 事件进行远程搜索,并改变选项。

可以通过 dropdown-scroll 监听下拉菜单的滚动事件。或者通过 dropdown-reach-bottom 监听下拉菜单滚动到底部的事件。

通过设置 allow-search ,可以让选择器支持对选项的搜索,配合 filter-option 可以自定义搜索。

选择框分为 minismallmediumlarge 四种尺寸。

当前示例同时展示了两种推荐写法:直接传空对象,观察 Select 默认补齐的固定 36px 行高;或者显式传 itemSize,让配置更直观。对于大多数下拉场景,只要提供弹层高度,默认固定高度模式就足够了。

通过 virtual-list-props 开启虚拟列表。Select 的下拉项当前默认按固定高度处理:如果你没有显式传 itemSizeminItemSize,组件会按 36px 选项高度补齐固定模式;如果要手动指定固定高度,请传 itemSize;只有显式传 minItemSize 时,才会切到动态高度模式。完整参数与迁移映射见 虚拟列表迁移指南

Select 在当前组件库里仍然保持 Arco Design Vue 的主要使用习惯,但实现已经完全收敛到本地的 TriggerSelectView、表单联动和主题体系。迁移时建议把它当作“标签名和少量扩展约定不变、交互和主题链路切到本地组件库”的替换。

Arco Design VueSD Design Vue说明
a-selectsd-select选择器主体
a-optionsd-option选项组件
a-optgroupsd-optgroup选项分组
v-model / model-valuev-model / model-value受控写法保持一致
popup-visiblepopup-visible下拉框显隐控制保持一致
:options:options仍支持对象数组数据源
field-namesfield-names仍支持映射 value / label / children
#label / #option / #header / #footer同名插槽常见模板插槽可以直接迁移
  1. 迁移后的下拉层、弹出容器、表单联动和主题注入都复用当前组件库内部实现,所以涉及浮层挂载、局部主题和表单校验的场景,优先使用 popup-containertrigger-propsConfigProvider,不要再额外包一层自定义 Teleport 或独立弹层。
  2. 当前版本不再对外暴露 render function 风格的自定义入口,选择框内容、多选标签和选项内容统一使用 labeltagoption 插槽。旧业务如果有 JSX / h() 风格的渲染函数,需要改成模板插槽。
  3. max-tag-count="responsive" 走的是当前组件库的响应式折叠策略:除非显式传 0,否则会尽量保留至少一个可见标签,再把剩余数量折叠到 +n。如果旧页面依赖“宽度不够时全部折叠”的表现,迁移后要重新验收。
  4. allow-clear 在当前组件里默认就是开启的;如果旧业务显式依赖不可清空,迁移时要补上 :allow-clear="false",不要假设默认行为和历史版本完全一致。
<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>
<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>
<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>
  1. 先替换组件标签:a-selecta-optiona-optgroup 分别替换为 sd-selectsd-optionsd-optgroup,先保证页面能渲染。
  2. 再迁移数据写法:如果原来已经使用 options / field-names,通常可以原样保留;如果历史代码混用了插槽选项和对象数组,建议先统一成一种。
  3. 接着处理自定义展示:把旧的渲染函数或外层包装逻辑收敛到 labeltagoptionheaderfooter 等插槽。
  4. 最后验收交互细节:重点检查远程搜索、多选折叠、浮层宽度、自定义挂载容器、表单校验和局部主题,确认它们已经切到当前组件库的行为链路。

Select 也保留了一部分 Naive UI 迁移所需的兼容面,重点是受控写法和弹层显隐别名;但整体交互仍然以当前组件库的 TriggerSelectView、插槽体系和主题体系为准。迁移时建议优先完成组件替换,再把 Naive 风格命名逐步收敛回本地 API。

Naive UISD Design Vue说明
n-selectsd-select选择器主体
v-model:valuev-model:value / v-model当前同时支持 Naive 风格和本地默认写法
show / default-showpopup-visible / default-popup-visible,同时兼容 show / defaultShow建议逐步迁回本地命名
optionsoptions对象数组数据源可直接保留
field-namesfield-names仍支持字段映射
multiplemultiple多选模式写法保持一致
max-tag-countmax-tag-count仍支持数字和 responsive
clearableallow-clear需要改为本地命名
filterableallow-search需要改为本地命名
render-tag / render-label#tag / #label对外 render function 已移除,统一改用插槽
  1. 当前版本只兼容 Naive 中最常用的受控别名,比如 valueshowdefaultShow。像 filterableclearable 这类语义型属性没有保留同名别名,迁移时要主动改成 allow-searchallow-clear
  2. 对外 render function 已经移除,原来依赖 render-tagrender-label、选项 render 回调的场景,需要改成 taglabeloption 插槽。
  3. 多选标签折叠走的是当前组件库的本地响应式策略,max-tag-count="responsive" 会尽量至少保留一个标签可见,再折叠剩余数量;如果旧页面依赖 Naive 的宽度收缩细节,需要单独回归。
  4. 弹层、滚动定位、局部主题和表单联动都接到本地实现了,所以迁移后不要继续依赖 Naive 私有 DOM、类名或外层包裹的额外定位逻辑。
<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>
<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>
  1. 先把 n-select 替换成 sd-select,保留原有 optionsv-model:value 等低成本兼容写法,让页面先恢复可用。
  2. 再统一属性命名:把 filterableclearableshowdefault-show 分别改成 allow-searchallow-clearpopup-visibledefault-popup-visible
  3. 接着迁移自定义渲染:把 render-tagrender-label 一类函数式扩展收敛成 taglabeloption 插槽。
  4. 最后回归交互细节:重点看多选标签折叠、远程搜索、清空按钮、弹层容器和表单联动,确认它们已经符合当前组件库的本地行为。
参数名描述类型默认值版本
multiple是否开启多选模式(多选模式默认开启搜索)booleanfalse
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是否为加载中状态booleanfalse
disabled是否禁用booleanfalse
error是否为错误状态booleanfalse
allow-clear是否允许清空booleantrue
allow-search是否允许搜索boolean | { retainInputValue?: boolean }true
allow-create是否允许创建booleanfalse
max-tag-count多选模式下,最多显示的标签数量。responsive 会自动收敛为组件当前支持的展示模式number | 'responsive''responsive'
popup-container弹出框的挂载容器string | HTMLElement-
bordered是否显示输入框的边框booleantrue
default-active-first-option是否在无值时默认选择第一个选项booleantrue2.43.0
popup-visible (v-model)是否显示下拉菜单boolean-
default-popup-visible弹出框默认是否可见(非受控模式)booleanfalse
unmount-on-close是否在下拉菜单关闭时销毁元素booleanfalse
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)true2.10.0
show-extra-options是否在下拉菜单中显示额外选项booleantrue2.10.0
value-key用于确定选项键值的属性名string'value'2.18.0
search-delay触发搜索事件的延迟时间number5002.18.0
limit多选时最多的选择个数number02.18.0
field-names自定义 SelectOptionData 中的字段SelectFieldNames-2.22.0
scrollbar是否开启虚拟滚动条boolean | ScrollbarPropstrue2.38.0
show-header-on-empty空状态时是否显示headerbooleanfalse
show-footer-on-empty空状态时是否显示footerbooleanfalse
tag-nowrap标签内容不换行booleanfalse2.56.1
事件名描述参数版本
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> | undefined
ev: Event
2.18.0
插槽名描述参数版本
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选项为空时的显示内容-
参数名描述类型默认值版本
value选项值(如不填,会从内容中获取)string|number|boolean|object-
label选项标签(如不填,会从内容中获取)string-
disabled是否禁用booleanfalse
tag-props展示的标签属性TagProps-2.8.0
extra额外数据。2.18.0 版本废弃,可使用对象形式的 value 扩展数据object-2.10.0
index用于手动指定选项的 indexnumber-2.20.0
参数名描述类型默认值
label选项组的标题string-
插槽名描述参数版本
label选项组的标题-2.10.0
/**
* @zh 选项
* @en Option
*/
type Option = string | number | SelectOptionData | SelectOptionGroup;
/**
* @zh 筛选
* @en Filter
*/
type FilterOption = boolean | ((inputValue: string, option: SelectOptionData) => boolean);
参数名描述类型默认值
value选项值string | number | boolean | Record<string, unknown>-
label选项内容string-
disabled是否禁用booleanfalse
tagProps选项对应的多选标签的属性Record<string, unknown>-
参数名描述类型默认值
isGroup是否为选项组true-
label选项组标题string-
options选项组中的选项SelectOption[]-
参数名描述类型默认值版本
items列表数据unknown[][]
keyField用于提取每项唯一键,支持字段名或函数string | ((item, index) => string | number)'key'
itemSize固定高度模式的 item 高度,传入后使用 RecycleScrollernumber | string | ((item, index) => number)-
minItemSize动态高度模式的最小 item 高度;未传 itemSize 时使用 DynamicScrollernumber | string32
buffer额外渲染缓冲区(像素)number200

其余参数与暴露方法请查看 虚拟列表迁移指南

当使用 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>