AutoComplete
基础表单基于 Bootstrap 5 的自动完成组件,AutoComplete 系列(AutoComplete、AutoCompleteMenu、AutoCompleteItem、AutoCompleteToken、AutoCompleteHint、AutoCompleteHighlighter)提供输入即搜索的候选下拉,支持单选/多选标签、键盘导航、输入提示、新建选项、匹配高亮、受控模式与自定义渲染
Component Demo
Basic usage and examples of the AutoComplete component
基础用法
输入文字即过滤选项,支持方向键导航、回车选中、Esc 关闭,默认不区分大小写并忽略变音标记, 匹配文本自动高亮
多选模式
multiple 模式将选中项渲染为标签,点击 × 移除;输入框为空时按退格键聚焦最后一个标签, 再按退格键移除
受控模式
当前选中:无。传入 selected 后变为受控组件, clearButton 在右侧显示清空按钮
输入提示
selectHint 开启后,第一个匹配项以灰色提示展示;按 Tab、光标在末尾时按方向键右或按回车 (selectHintOnEnter)直接选中提示
创建新选项
没有精确匹配时菜单末尾出现带前缀的新建选项,选中后加入选中列表(不修改原始 options), 可通过 onChange 感知
匹配高亮
默认菜单项使用 AutoCompleteHighlighter 渲染,匹配部分加粗展示; 也可用 renderMenuItemChildren 完全自定义
自定义菜单
renderMenu 接收结果集与菜单属性,配合 AutoCompleteMenu/AutoCompleteItem 组合自定义内容; minLength 限制输入长度,无结果时菜单显示 emptyLabel
尺寸
size 分别渲染 `form-control-lg`/`form-control-sm` 类,与 Bootstrap 表单尺寸规则一致
禁用与校验状态
disabled 禁用输入框;isValid/isInvalid 渲染 `is-valid`/`is-invalid` 类并影响多选容器的 聚焦样式
API Documentation
Complete API reference for the AutoComplete component
Props
AutoComplete
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
align | AutoCompleteAlign | 'justify' | 菜单对齐方式,`"justify"` 菜单与输入框等宽,`"left"`/`"right"` 分别对齐输入框的左/右边缘 |
allowNew | AutoCompleteAllowNew | false | 是否允许创建新选项,可传函数接收当前结果集与过滤上下文自行判断;新建选项仅加入选中列表,不会修改原始 options |
as | ElementType | 'div' | 根元素标签 |
autoFocus | boolean | false | 组件挂载后自动聚焦输入框 |
caseSensitive | boolean | false | 是否区分大小写过滤选项 |
children | AutoCompleteRenderProps | - | 组件内容;传函数时接收渲染属性(activeIndex、getInputProps、isMenuShown、results 等)用于自定义组合 |
clearButton | boolean | false | 有选中项时在输入框右侧显示清空按钮 |
className | string | - | 根元素自定义类名 |
defaultInputValue | string | '' | 非受控模式下的初始输入值 |
defaultOpen | boolean | false | 非受控模式下菜单初始是否展开 |
defaultSelected | T[] | [] | 非受控模式下的初始选中项 |
disabled | boolean | false | 禁用输入框 |
dropup | boolean | false | 菜单向上展开,默认向下 |
emptyLabel | ReactNode | 'No matches found.' | 没有匹配结果时显示的提示内容 |
flip | boolean | false | 菜单靠近视口边缘时是否翻转到相反方向 |
highlightOnlyResult | boolean | false | 只有一个结果时高亮该项并允许按回车直接选中,与 allowNew 同时设置时失效 |
id | string | number | - | 组件 id,用于 aria-owns/aria-activedescendant 关联与菜单 id,无障碍访问必需 |
ignoreDiacritics | boolean | true | 过滤时是否忽略重音符号等变音标记 |
inputProps | AutoCompleteInputProps | - | 直接透传给输入框的属性(onBlur、onChange、onFocus、onKeyDown 除外) |
isInvalid | boolean | false | 无效校验状态,渲染 `is-invalid` 类 |
isValid | boolean | false | 有效校验状态,渲染 `is-valid` 类 |
labelKey | AutoCompleteLabelKey | 'label' | 选项的显示字段名或返回显示字符串的函数,字符串选项直接使用自身 |
maxHeight | string | '300px' | 菜单最大高度,超出后滚动 |
maxResults | number | 100 | 菜单最多显示的结果数量 |
minLength | number | 0 | 输入达到多少字符后才显示菜单 |
multiple | boolean | false | 是否允许多选,选中项渲染为可删除的标签(AutoCompleteToken) |
newSelectionPrefix | ReactNode | 'New selection: ' | 新建选项的展示前缀,仅 allowNew 生效时有效 |
onBlur | (event) => void | - | 输入框失焦回调 |
onChange | (selected: T[]) => void | - | 选中项增删时触发,接收最新选中项数组 |
onFocus | (event) => void | - | 输入框聚焦回调 |
onInputChange | (text, event) => void | - | 输入值变化回调,接收当前文本与原生事件 |
onKeyDown | (event) => void | - | 输入框按键回调,在内部键盘导航处理之后触发 |
onMenuToggle | (show: boolean) => void | - | 菜单显隐变化回调 |
open | boolean | - | 受控的菜单展开状态,优先级高于内部状态 |
options | readonly T[] | - | 候选选项集,元素为字符串或对象 |
placeholder | string | - | 输入框占位文本 |
renderInput | (inputProps, state) => ReactNode | - | 自定义输入渲染,接收输入框属性(含 inputRef/referenceElementRef)与渲染属性;多选时需自行渲染选中项 |
renderMenu | (results, menuProps, state) => ReactNode | - | 自定义菜单渲染,接收结果集、菜单属性(展开到 AutoCompleteMenu 或容器)与渲染属性 |
renderMenuItemChildren | (option, props, index) => ReactNode | - | 自定义菜单项内容,接收选项、active/disabled 状态与索引 |
renderToken | (option, props, index) => ReactNode | - | 自定义多选标签渲染,接收选项、标签属性与索引 |
selectHint | AutoCompleteSelectHint | false | 是否显示输入提示(Hint),可按 Tab 或光标在末尾时按方向键右选中提示;传函数可在选中前自定义判断 |
selectHintOnEnter | boolean | false | 存在提示时按回车直接选中提示项(第一个结果) |
selected | T[] | - | 受控的选中项数组 |
size | AutoCompleteSize | - | 输入框尺寸,`lg`/`sm` 渲染 `form-control-lg`/`form-control-sm` |
AutoCompleteMenu
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
as | ElementType | 'div' | 菜单容器标签,默认渲染 `div.dropdown-menu` |
emptyLabel | ReactNode | 'No matches found.' | 没有子项时显示的提示内容 |
id | string | - | 菜单 id,同时作为输入框 aria-owns 的关联目标 |
maxHeight | string | '300px' | 菜单最大高度,超出后滚动 |
AutoCompleteItem
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
active | boolean | - | 激活状态,默认由菜单内 position 与当前激活索引比对得出 |
as | ElementType | 'a' | 菜单项标签,默认渲染 `a.dropdown-item` |
children | ReactNode | - | 菜单项内容,默认渲染高亮后的选项标签 |
disabled | boolean | - | 禁用状态,默认读取选项的 disabled 字段 |
href | string | '#' | 渲染为 `a` 标签时的链接地址 |
labelKey | AutoCompleteLabelKey | - | 覆盖上下文的 labelKey,用于默认内容渲染 |
onSelect | (option, event) => void | - | 选择回调,事件未阻止时继续触发 AutoComplete 的选择逻辑 |
option | AutoCompleteOption | - | 选项对象,选择时通过上下文提交给 AutoComplete |
position | number | - | 选项索引,用于激活状态与 aria-activedescendant 关联 |
AutoCompleteToken
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
children | ReactNode | - | 标签内容,通常为选项的显示文本 |
disabled | boolean | false | 禁用标签,不显示移除按钮且不可交互 |
onRemove | () => void | - | 移除回调,设置后渲染移除按钮;聚焦标签时按退格键也可移除 |
tabIndex | number | 0 | 标签的 tabIndex,仅在可移除时生效 |
AutoCompleteHint
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
children | ReactNode | - | 被包裹的输入框元素,Hint 会在其后追加一层透明提示输入框 |
AutoCompleteHighlighter
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
children | string | - | 要高亮的文本内容 |
className | string | - | 匹配文本的 mark 元素类名,默认加粗展示 |
search | string | - | 搜索文本,不区分大小写与变音标记匹配 |
Common Props
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
...rest | HTMLAttributes | - | 透传原生元素属性(如 onClick、style 等) |
Type Definitions
AutoCompleteOption
候选选项类型,支持字符串与对象
export type AutoCompleteOption = object | string;AutoCompleteLabelKey
选项显示字段名或显示函数类型
export type AutoCompleteLabelKey<T> = ((option: T) => string) | string;AutoCompleteAlign
菜单对齐方式类型
export type AutoCompleteAlign = 'justify' | 'left' | 'right';AutoCompleteAllowNew
新建选项策略类型
export type AutoCompleteAllowNew<T extends AutoCompleteOption> =
((results: T[], context: AutoCompleteFilterContext<T>) => boolean) | boolean;AutoCompleteSelectHint
输入提示选中策略类型
export type AutoCompleteSelectHint =
((shouldSelect: boolean, event: KeyboardEvent<HTMLInputElement>) => boolean) | boolean;AutoCompleteSize
输入框尺寸类型
export type AutoCompleteSize = 'lg' | 'sm';AutoCompleteFilterContext
过滤与新建判断的上下文接口
export interface AutoCompleteFilterContext<T extends AutoCompleteOption> {
allowNew: AutoCompleteAllowNew<T>;
caseSensitive: boolean;
ignoreDiacritics: boolean;
labelKey: AutoCompleteLabelKey<T>;
text: string;
}AutoCompleteRenderProps
渲染属性接口,用于 children 函数与自定义渲染
export interface AutoCompleteRenderProps<T extends AutoCompleteOption = AutoCompleteOption> {
activeIndex: number;
getInputProps: (props?: AutoCompleteInputProps) => AutoCompleteInputProps;
hideMenu: () => void;
isMenuShown: boolean;
labelKey: AutoCompleteLabelKey<AutoCompleteOption>;
onClear: () => void;
onRemove: (option: AutoCompleteOption) => void;
results: T[];
selected: T[];
text: string;
toggleMenu: () => void;
}AutoCompleteInputProps
输入框属性接口,附加 inputRef/referenceElementRef 用于自定义渲染
export interface AutoCompleteInputProps extends InputHTMLAttributes<HTMLInputElement> {
inputRef?: (element: HTMLInputElement | null) => void;
referenceElementRef?: (element: HTMLElement | null) => void;
}AutoCompleteProps
AutoComplete 组件属性接口
export interface AutoCompleteProps<T extends AutoCompleteOption> extends Omit<
HTMLAttributes<HTMLElement>,
'children' | 'id' | 'onBlur' | 'onChange' | 'onFocus' | 'onKeyDown'
> {
align?: AutoCompleteAlign;
allowNew?: AutoCompleteAllowNew<T>;
as?: ElementType;
autoFocus?: boolean;
caseSensitive?: boolean;
children?: ((props: AutoCompleteRenderProps<T>) => ReactNode) | ReactNode;
clearButton?: boolean;
className?: string;
defaultInputValue?: string;
defaultOpen?: boolean;
defaultSelected?: T[];
disabled?: boolean;
dropup?: boolean;
emptyLabel?: ReactNode;
flip?: boolean;
highlightOnlyResult?: boolean;
id: string | number;
ignoreDiacritics?: boolean;
inputProps?: AutoCompleteInputProps;
isInvalid?: boolean;
isValid?: boolean;
labelKey?: AutoCompleteLabelKey<T>;
maxHeight?: string;
maxResults?: number;
minLength?: number;
multiple?: boolean;
newSelectionPrefix?: ReactNode;
onBlur?: (event: FocusEvent<HTMLInputElement>) => void;
onChange?: (selected: T[]) => void;
onFocus?: (event: FocusEvent<HTMLInputElement>) => void;
onInputChange?: (text: string, event: ChangeEvent<HTMLInputElement>) => void;
onKeyDown?: (event: KeyboardEvent<HTMLInputElement>) => void;
onMenuToggle?: (show: boolean) => void;
open?: boolean;
options: readonly T[];
placeholder?: string;
renderInput?: (
inputProps: AutoCompleteInputProps,
state: AutoCompleteRenderProps<T>,
) => ReactNode;
renderMenu?: (
results: T[],
menuProps: AutoCompleteMenuProps,
state: AutoCompleteRenderProps<T>,
) => ReactNode;
renderMenuItemChildren?: (
option: T,
props: AutoCompleteMenuItemRenderProps,
index: number,
) => ReactNode;
renderToken?: (option: T, props: AutoCompleteTokenProps, index: number) => ReactNode;
selectHint?: AutoCompleteSelectHint;
selectHintOnEnter?: boolean;
selected?: T[];
size?: AutoCompleteSize;
}AutoCompleteItemProps
AutoCompleteItem 组件属性接口
export interface AutoCompleteItemProps extends Omit<
HTMLAttributes<HTMLElement>,
'children' | 'onSelect'
> {
active?: boolean;
as?: ElementType;
children?: ReactNode;
className?: string;
disabled?: boolean;
href?: string;
labelKey?: AutoCompleteLabelKey<AutoCompleteOption>;
onSelect?: (option: AutoCompleteOption, event: MouseEvent<HTMLElement>) => void;
option: AutoCompleteOption;
position: number;
}AutoCompleteTokenProps
AutoCompleteToken 组件属性接口
export interface AutoCompleteTokenProps extends HTMLAttributes<HTMLElement> {
children?: ReactNode;
className?: string;
disabled?: boolean;
onRemove?: () => void;
tabIndex?: number;
}AutoCompleteHintProps
AutoCompleteHint 组件属性接口
export interface AutoCompleteHintProps extends HTMLAttributes<HTMLDivElement> {
children?: ReactNode;
className?: string;
}AutoCompleteHighlighterProps
AutoCompleteHighlighter 组件属性接口
export interface AutoCompleteHighlighterProps {
children: string;
className?: string;
search: string;
}AutoCompleteContextValue
AutoComplete 上下文,供菜单项与提示框等消费
export interface AutoCompleteContextValue {
activeIndex: number;
hintText: string;
id: string | number;
inputNode: HTMLInputElement | null;
labelKey: AutoCompleteLabelKey<AutoCompleteOption>;
onActiveIndexChange: (index: number) => void;
onItemClick: (option: AutoCompleteOption) => void;
text: string;
}