---
title: Select 选择器
description: 下拉选择,支持筛选、多选、远程搜索、触底加载与自由输入
---
# Select 选择器
`Select` 从一个列表里选值,是表单里最常被用到的控件之一。它把触发器做成了**输入框**:开启筛选后可直接键入过滤,键盘也能完成全部操作。
## 何时使用
- 选项较多(> 5 个)时;
- 选项来自接口、需要分页或远程搜索时;
- 需要多选,且选项数量不足以用 Checkbox 平铺时;
- 选项很少(2-5 个)且需要一次看全时,用 [Radio](/ui/form/radio) / [Segmented](/ui/general/segmented) 更快。
## 基础用法
`options` 默认按 `{ label, value, disabled }` 取值。
## 字段名映射
后端返回的字段名不是 `label` / `value` 时,用 `labelKey` / `valueKey` 映射,不必在业务侧做数据转换。
## 多选
`multiple` 时 `modelValue` 为数组,选中后下拉保持打开,选中项以顿号拼接显示。
## 筛选
`filterable` 默认就是开启的;不传时按 `label` / `value` 做大小写不敏感的包含匹配,也可以传 `filterOption` 自定义。
## 远程搜索
`remote` 模式不会做本地筛选,全部交给父层:输入触发 `search`,父层把结果写回 `options`;`loading` 时右侧显示加载图标而不是箭头/清除按钮。
## 触底加载更多
列表滚到底部会持续触发 `loadMore`,配合 `loading` 去重;`#footer` 插槽可以放加载提示。
## 自定义选项
不传 `options` 时使用默认插槽,插槽透出 `{ select, close }`,适合做带描述、头像的富选项。
## 键盘操作
| 按键 | 行为 |
| --- | --- |
| `↓` / `↑` | 打开下拉(若未打开)或移动高亮(跳过分隔项与禁用项) |
| `Home` / `End` | 跳到第一个 / 最后一个可选项 |
| `Enter` | 选中当前高亮项;若输入文本精确匹配某项 label,优先选中它 |
| `Esc` | 关闭下拉并清空筛选词 |
| `Tab` | 关闭下拉并把焦点交给下一个控件 |
| 直接输入 | 筛选列表(`filterable` 为 true 时) |
## API
### Props
| 名称 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `modelValue` | `string \| number \| boolean \| object \| null \| Array` | — | 双向绑定的值;`multiple` 时为数组 |
| `options` | `Array \| string \| number>` | — | 选项数组。元素为对象时按 `labelKey` / `valueKey` / `disabled` 取值,为原始值时自身即 label 与 value |
| `disabled` | `boolean` | `false` | 禁用态 |
| `clearable` | `boolean` | `false` | 有值时显示清除按钮(聚焦时出现) |
| `multiple` | `boolean` | `false` | 多选模式,`modelValue` 为数组 |
| `filterable` | `boolean` | `true` | 是否开启筛选(关闭时输入框只读) |
| `filterOption` | `(input: string, option: unknown) => boolean` | — | 自定义筛选函数,`option` 是**原始**选项对象 |
| `remote` | `boolean` | `false` | 远程搜索模式:不做本地筛选,输入时触发 `search` |
| `loading` | `boolean` | `false` | 加载中:右侧显示加载图标,并阻止触底重复触发 |
| `notFoundText` | `string` | 语言包 | 无匹配项时的文案 |
| `allowFreeInput` | `boolean` | `false` | 允许自由输入:不在列表里的文本也可以作为值提交 |
| `labelKey` | `string` | `'label'` | 选项对象中作为显示文本的字段名 |
| `valueKey` | `string` | `'value'` | 选项对象中作为值的字段名 |
### Events
| 名称 | 参数 | 说明 |
| --- | --- | --- |
| `update:modelValue` | `(value: SelectValue \| SelectValue[])` | 选中 / 清除时触发;覆盖多选 |
| `change` | `(value, option?)` | 同上,第二个参数是被选中的规范化选项(清除时为 `undefined`) |
| `search` | `(query: string)` | `remote` 模式下输入时触发 |
| `visibleChange` | `(open: boolean)` | 下拉展开 / 收起。远程型调用方可据此在展开时拉取首页数据 |
| `loadMore` | `()` | 列表滚动触底(距底 24px 内),已加载中不重复触发 |
### Slots
| 名称 | 参数 | 说明 |
| --- | --- | --- |
| `default` | `{ select: (value) => void; close: () => void }` | 自定义选项(不传 `options` 时生效) |
| `footer` | `{ loading: boolean }` | 列表底部内容,如加载更多提示 |
### Exposed
| 名称 | 签名 | 说明 |
| --- | --- | --- |
| `openDropdown` | `() => void` | 展开下拉 |
| `closeDropdown` | `() => void` | 收起下拉 |
### 类型定义
```ts
export type SelectValue = string | number | boolean | object | null | undefined
export interface SelectProps {
modelValue?: SelectValue | SelectValue[]
options?: Array | string | number>
disabled?: boolean
clearable?: boolean
multiple?: boolean
filterable?: boolean
filterOption?: (input: string, option: unknown) => boolean
remote?: boolean
loading?: boolean
notFoundText?: string
allowFreeInput?: boolean
labelKey?: string
valueKey?: string
}
```
### 样式变量
| 变量 | 默认值 | 说明 |
| --- | --- | --- |
| `--g3-select-dropdown-max-height` | `256px` | 下拉最大高度 |
| `--g3-select-dropdown-max-width` | `360px` | 下拉宽度上限(触发框更宽时以触发框为准) |
| `--g3-control-height` | `32px` | 触发器高度 |
| `--g3-color-primary-ring` | 主色 20% | 聚焦环 |
## 实现说明
- **触发器就是输入框**:这样「键入筛选」与「键盘导航」共用一套焦点管理,不需要额外的隐藏 input;关闭下拉时会清空筛选词并回显选中项;
- **自由输入的提交时机**:输入过程**不**写 `modelValue`(避免把半成品写进表单),只在失焦或关闭下拉时提交;非自由输入模式下,若文本精确匹配某选项 label 则选中该项,否则回退到上次选中值;
- **焦点回流**:选中 / 清除后下拉内容会卸载,焦点会掉到 `body`;组件会把焦点主动交还输入框,并用 `suppressNextAutoOpen` 抑制这次「聚焦即展开」,否则下拉会立刻弹回来;
- **点击外部关闭**用的浮层基座是 [Popover](/ui/overlay/popover):Teleport 到配置的容器、滚动 / 尺寸变化时重算位置、Esc 关闭;
- 下拉宽度取 `max(触发框宽, 内容宽)` 并由 `--g3-select-dropdown-max-width` 封顶,超出上限的选项文案折行而不是把下拉拉出屏幕;
- 选项用 `v-memo` 缓存(只在「该选项或它是否是高亮项」变化时重渲染),长列表下键盘连续移动不会卡顿。