--- title: Select 选择器 description: 下拉选择,支持筛选、多选、远程搜索、触底加载与自由输入 --- # Select 选择器 `Select` 从一个列表里选值,是表单里最常被用到的控件之一。它把触发器做成了**输入框**:开启筛选后可直接键入过滤,键盘也能完成全部操作。 ## 何时使用 - 选项较多(> 5 个)时; - 选项来自接口、需要分页或远程搜索时; - 需要多选,且选项数量不足以用 Checkbox 平铺时; - 选项很少(2-5 个)且需要一次看全时,用 [Radio](/ui/form/radio) / [Segmented](/ui/general/segmented) 更快。 ## 基础用法 `options` 默认按 `{ label, value, disabled }` 取值。 :::demo{name="select/basic"} ::: ## 字段名映射 后端返回的字段名不是 `label` / `value` 时,用 `labelKey` / `valueKey` 映射,不必在业务侧做数据转换。 :::demo{name="select/field-names"} ::: ## 多选 `multiple` 时 `modelValue` 为数组,选中后下拉保持打开,选中项以顿号拼接显示。 :::demo{name="select/multiple"} ::: ## 筛选 `filterable` 默认就是开启的;不传时按 `label` / `value` 做大小写不敏感的包含匹配,也可以传 `filterOption` 自定义。 :::demo{name="select/filterable"} ::: ## 远程搜索 `remote` 模式不会做本地筛选,全部交给父层:输入触发 `search`,父层把结果写回 `options`;`loading` 时右侧显示加载图标而不是箭头/清除按钮。 :::demo{name="select/remote"} ::: ## 触底加载更多 列表滚到底部会持续触发 `loadMore`,配合 `loading` 去重;`#footer` 插槽可以放加载提示。 :::demo{name="select/load-more"} ::: ## 自定义选项 不传 `options` 时使用默认插槽,插槽透出 `{ select, close }`,适合做带描述、头像的富选项。 :::demo{name="select/custom-option"} ::: ## 键盘操作 | 按键 | 行为 | | --- | --- | | `↓` / `↑` | 打开下拉(若未打开)或移动高亮(跳过分隔项与禁用项) | | `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` 缓存(只在「该选项或它是否是高亮项」变化时重渲染),长列表下键盘连续移动不会卡顿。