Skip to content

Select 下拉选择

从一组选项中选择。支持单选、多选、清空与键盘导航。

基础用法

vue
<script setup>
import { ref } from 'vue'

const options = [
  { label: '管理员', value: 'admin' },
  { label: '编辑', value: 'editor' },
  { label: '已停用的角色', value: 'disabled', disabled: true }
]

const picked = ref('admin')
</script>

<template>
  <SrSelect v-model="picked" :options="options" />
</template>

当前值:admin

多选

multiple 开启多选,值变为数组。超过 maxTagCount 时折叠为 +N

vue
<SrSelect v-model="picked" multiple :options="options" />
<SrSelect v-model="picked" multiple :max-tag-count="2" :options="options" />

maxTagCount 影响的是显示,不是值

折叠成 +2 只是视觉上的收纳,v-model 拿到的仍是完整的数组

清空与禁用项

vue
<SrSelect v-model="picked" clearable :options="options" />
<SrSelect v-model="picked" disabled :options="options" />

选项级的 disabled 位于 options 数组里(见上面的「已停用的角色」), 它会阻止选中但仍显示在列表里——直接过滤掉会让用户以为「这个人不存在了」。

键盘操作

下拉打开后:

按键作用
↑ / ↓在选项间移动
Enter选中当前项
Esc关闭下拉

禁用项会被跳过——焦点不会停在不可选的项上。

浮层定位

下拉面板会自动校正视口边缘:靠近窗口底部时向上展开, 靠近左右边缘时横向对齐。offset 控制面板与触发器之间的距离。

关于浮层与 overflow

下拉面板通过 Teleport 挂到 body,因此不会被父容器的 overflow: hidden 裁掉

但这也意味着它不受父容器的 transform 影响—— 若触发器本身在一个缩放或平移的容器里,面板位置会按视口坐标计算, 可能与触发器错位。这类场景需要把选择器移出该容器。

尺寸

vue
<SrSelect size="sm" :options="options" />
<SrSelect size="md" :options="options" />
<SrSelect size="lg" :options="options" />

Props

名称类型默认值说明
modelValueSelectValue | SelectValue[]当前值,多选时为数组
options{ label, value, disabled? }[][]选项列表
placeholderstring未选中时的占位文本
size'sm' | 'md' | 'lg''md'尺寸
disabledbooleanfalse是否禁用
clearablebooleanfalse是否可清空
invalidbooleanfalse是否处于错误态
multiplebooleanfalse是否多选
maxTagCountnumber多选时最多显示几个标签
offsetnumber下拉面板与触发器的距离

事件

事件参数说明
update:modelValue当前值选中项变化
change当前值同上(语义化事件)

无障碍

  • 触发器带 role="combobox"aria-expanded,读屏软件能播报展开状态
  • 选项列表带 role="listbox",每项 role="option"aria-selected
  • 键盘完全可用(上下键 + 回车 + Esc),不依赖鼠标

触发器为何是只读的

它视觉上复用了输入框样式,但是 readonly 的——避免用户手输一半、 值与选项都对不上。

「可搜索的下拉」是另一种组件:它的输入框要接受任意文本并实时过滤, 与「从固定选项里选」是两个职责,不该压进同一个触发器。

自用组件库 · 源码分发 · 不发布 npm