ant-design AutoComplete 自动完成组件深度解析:从 API 全量参数到 Select Combobox 底层实现
【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/GitHub_Trending/an/ant-design
本文基于 ant-design 仓库中的 AutoComplete 组件文档,系统讲解自动完成组件的适用场景、全部 API 参数与事件回调、查询模式实战写法,并结合 AutoComplete 源码 剖析其“本质上是 Select 的 combobox 模式”这一底层设计。读完本文,你可以独立完成邮箱补全、搜索建议、分组类目查询等常见录入场景,并理解options/showSearch/classNames等配置项在源码中的真实生效路径。
何时使用:AutoComplete 与 Select 的本质区别
文档给出的使用边界非常明确——当你需要一个输入框而不是选择器,或者需要输入建议/辅助提示时,才应该使用 AutoComplete。它与 Select 的区别在于设计意图:
- AutoComplete 是一个带提示的文本输入框,用户可以自由输入,关键词是辅助输入;
- Select 是在限定的可选项中进行选择,关键词是选择。
从源码结构看,这个定位直接体现在实现方式上:AutoComplete.tsx 并没有独立实现一套下拉逻辑,而是在第 263~288 行直接渲染<Select>,并传入内部常量:
mode={Select.SECRET_COMBOBOX_MODE_DO_NOT_USE as SelectProps['mode']}在 Select 组件 中,该常量会被映射为 rc-select 的'combobox'模式:
if (m === SECRET_COMBOBOX_MODE_DO_NOT_USE) { return 'combobox'; }也就是说,AutoComplete 是 Select 在 combobox 模式下的受控封装,下拉面板、虚拟滚动、键盘导航、焦点管理等能力全部复用自 Select。这一点也解释了为什么它的主题 Token 文档直接引用 Select 的 Token 表(原文档中<ComponentTokenTable component="Select">)。
代码演示:覆盖文档中的全部实战场景
文档共提供 10 个正式 demo 和 7 个 Debug 场景。以下按文档顺序逐一讲解关键场景的核心代码,代码均可在 demo 目录 中找到对应文件。
1. 基本使用:onSearch 驱动 options
基本用法的核心是通过showSearch.onSearch在用户输入时更新options(见 basic.tsx):
import { AutoComplete } from 'antd'; import type { AutoCompleteProps } from 'antd'; const mockVal = (str: string, repeat = 1) => ({ value: str.repeat(repeat), }); const App = () => { const [value, setValue] = useState(''); const [options, setOptions] = useState<AutoCompleteProps['options']>([]); const getPanelValue = (searchText: string) => !searchText ? [] : [mockVal(searchText), mockVal(searchText, 2), mockVal(searchText, 3)]; return ( <> <AutoComplete options={options} style={{ width: 200 }} showSearch={{ onSearch: (text) => setOptions(getPanelValue(text)), }} placeholder="input here" /> <br /> <br /> {/* 受控模式:value + onChange */} <AutoComplete value={value} showSearch={{ onSearch: (text) => setOptions(getPanelValue(text)) }} options={options} style={{ width: 200 }} onChange={(data) => setValue(data)} placeholder="control mode" /> </> ); };注意受控示例中用onChange管理value,而不是onSearch,这一点与文末 FAQ 中“受控状态下请勿用 onSearch 管理中文输入”的结论一致。
2. 自定义选项:邮箱补全
options支持label与value分离的数据化配置,相比 jsx 定义渲染性能更好。以邮箱补全为例(见 options.tsx):
const [options, setOptions] = React.useState<AutoCompleteProps['options']>([]); const handleSearch = (value: string) => { setOptions(() => { if (!value || value.includes('@')) { return []; } return ['gmail.com', '163.com', 'qq.com'].map((domain) => ({ label: `${value}@${domain}`, value: `${value}@${domain}`, })); }); }; return ( <AutoComplete style={{ width: 200 }} showSearch={{ onSearch: handleSearch }} placeholder="input here" options={options} /> );当输入包含@后返回空数组,下拉自动收起——这正是 FAQ 中“options 为空时不展示下拉菜单”行为的典型应用。
3. 自定义输入组件
通过children传入自定义输入框(类型限定为HTMLInputElement | HTMLTextAreaElement | <InputProps 的 ReactElement>,默认<Input />)。custom.tsx 展示了用TextArea替换默认输入框的写法:
<AutoComplete options={options} style={{ width: 200 }} onSelect={onSelect} showSearch={{ onSearch: handleSearch }}> <TextArea placeholder="input here" className="custom" style={{ height: 50 }} onKeyPress={handleKeyPress} /> </AutoComplete>源码中 AutoComplete.tsx 第 132~143 行 对children做了甄别:当 children 是唯一元素且不是Select.Option/OptGroup时,才会被识别为自定义输入组件,并通过内部 APIgetInputElement透传给 Select。同时源码在开发环境下有一条 warning:使用自定义输入组件时不应再设置size,需要自行控制尺寸样式。
4. 不区分大小写:showSearch.filterOption
筛选逻辑挂在showSearch.filterOption上,函数接收inputValue与option两个参数(见 non-case-sensitive.tsx):
<AutoComplete style={{ width: 200 }} options={options} placeholder="try to type `b`" showSearch={{ filterOption: (inputValue, option) => option!.value.toUpperCase().includes(inputValue.toUpperCase()), }} />需要特别注意:顶层的filterOption、onSearch、dataSource等均已废弃(见下文 API 表),筛选相关能力统一收敛到showSearch对象中。
5. 查询模式:确定类目与不确定类目
这是文档中最贴近真实业务的两组 demo。
确定类目(certain-category.tsx):options支持二级结构,第一层是带label+options的分组标题,常用于搜索结果按 Libraries/Solutions/Articles 等类目展示,并配合Input.Search作为自定义输入组件:
const options = [ { label: <Title title="Libraries" />, options: [renderItem('AntDesign', 10000), renderItem('AntDesign UI', 10600)], }, { label: <Title title="Solutions" />, options: [renderItem('AntDesign UI FAQ', 60100), renderItem('AntDesign FAQ', 30010)], }, // ... ]; <AutoComplete classNames={{ popup: { root: styles.categorySearch } }} popupMatchSelectWidth={500} style={{ width: 250 }} options={options} > <Input.Search size="large" placeholder="input here" /> </AutoComplete>注意这里popupMatchSelectWidth传入了数字500,即下拉菜单最小宽度固定为 500px,允许内容比输入框更宽。
不确定类目(uncertain-category.tsx):搜索结果数量未知,onSearch返回带链接和结果数的扁平选项列表,输入框使用带按钮的Input.Search:
<AutoComplete popupMatchSelectWidth={252} style={{ width: 300 }} options={options} onSelect={onSelect} showSearch={{ onSearch: handleSearch }}> <Input.Search size="large" placeholder="input here" enterButton /> </AutoComplete>6. 其他正式场景速览
- 自定义状态(status.tsx):
status="error"/status="warning"设置校验态边框与提示样式; - 多种形态(variant.tsx,5.13.0 起):
variant支持outlined(默认)/borderless/filled/underlined; - 自定义清除按钮(allowClear.tsx):
allowClear自 5.8.0 起支持对象形式allowClear={{ clearIcon: <CloseSquareFilled /> }}替换默认清除图标; - 自定义语义结构的样式和类(style-class.tsx,6.0.0 起):通过
classNames/styles精确定位root、input、popup等语义节点。
7. Debug 场景
文档还列出了 7 个 debug demo,用于回归验证特定缺陷修复,包括自定义输入组件配合清除按钮、禁用自定义输入、Form 中的禁用文字颜色、填充形态自定义输入、Form 集成,以及AutoComplete._InternalPanelDoNotUseOrYouWillBeFired静态面板(见 render-panel.tsx)。该静态面板在 index.tsx 中由genPurePanel生成,命名中的 “DoNotUse” 提示它仅用于调试预览,不建议在业务中使用。
完整 API 参考
通用属性参考:通用属性。
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| allowClear | 支持清除 | boolean | { clearIcon?: ReactNode } | false | 5.8.0: 支持对象形式 |
| backfill | 使用键盘选择选项的时候把选中项回填到输入框中 | boolean | false | |
| children | 自定义输入框 | HTMLInputElement | HTMLTextAreaElement | React.ReactElement<InputProps> | <Input /> | |
| classNames | 用于自定义组件内部各语义化结构的 class,支持对象或函数 | Record<SemanticDOM, string> | (info: { props })=> Record<SemanticDOM, string> | - | |
自动完成的数据源,请使用options替代 | DataSourceItemType[] | - | - | |
| defaultActiveFirstOption | 是否默认高亮第一个选项 | boolean | true | |
| defaultOpen | 是否默认展开下拉菜单 | boolean | - | |
| defaultValue | 指定默认选中的条目 | string | - | |
| disabled | 是否禁用 | boolean | false | |
下拉菜单的 className 属性,请使用classNames.popup.root替代 | string | - | - | |
下拉菜单和输入框是否同宽,请使用popupMatchSelectWidth替代 | boolean | number | true | - | |
自定义下拉框内容,使用popupRender替换 | (originNode: ReactElement) => ReactNode | - | 4.24.0 | |
| popupRender | 自定义下拉框内容 | (originNode: ReactElement) => ReactNode | - | |
下拉菜单的 className 属性,使用classNames.popup.root替换 | string | - | 4.23.0 | |
下拉菜单的 style 属性,使用styles.popup.root替换 | CSSProperties | - | ||
| popupMatchSelectWidth | 下拉菜单和选择器同宽。默认将设置min-width,当值小于选择框宽度时会被忽略。false 时会关闭虚拟滚动 | boolean | number | true | |
是否根据输入项进行筛选。当其为一个函数时,会接收inputValue、option两个参数 | boolean | function(inputValue, option) | true | ||
| getPopupContainer | 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位 | function(triggerNode) | () => document.body | |
| notFoundContent | 当下拉列表为空时显示的内容 | ReactNode | - | |
| open | 是否展开下拉菜单 | boolean | - | |
| options | 数据化配置选项内容,相比 jsx 定义会获得更好的渲染性能 | { label, value }[] | - | |
| placeholder | 输入框提示 | string | - | |
| showSearch | 搜索配置 | true | Object | true | |
| status | 设置校验状态 | 'error' | 'warning' | - | 4.19.0 |
| size | 控件大小 | large|medium|small | - | |
| styles | 用于自定义组件内部各语义化结构的行内 style,支持对象或函数 | Record<SemanticDOM, CSSProperties> | (info: { props })=> Record<SemanticDOM, CSSProperties> | - | |
| value | 指定当前选中的条目 | string | - | |
| variant | 形态变体 | outlined|borderless|filled|underlined | outlined | 5.13.0 |
| virtual | 设置 false 时关闭虚拟滚动 | boolean | true | 4.1.0 |
| onBlur | 失去焦点时的回调 | function() | - | |
| onChange | 选中 option,或 input 的 value 变化时,调用此函数 | function(value) | - | |
展开下拉菜单的回调,使用onOpenChange替换 | (open: boolean) => void | |||
| onOpenChange | 展开下拉菜单的回调 | (open: boolean) => void | - | |
| onFocus | 获得焦点时的回调 | function() | - | |
| 搜索补全项的时候调用 | function(value) | - | ||
| onSelect | 被选中时调用,参数为选中项的 value 值 | function(value, option) | - | |
| onClear | 清除内容时的回调 | function | - | 4.6.0 |
| onInputKeyDown | 按键按下时回调 | (event: KeyboardEvent) => void | - | |
| onPopupScroll | 下拉列表滚动时的回调 | (event: UIEvent) => void | - |
废弃属性的源码级迁移对照
上表中的废弃项并非只是文档约定,源码 AutoComplete.tsx 第 188~200 行 在开发环境下会对它们逐条触发 deprecation warning,并内置了官方迁移映射:
| 废弃属性 | 替代方案(源码 deprecatedProps 映射) |
|---|---|
| dropdownMatchSelectWidth | popupMatchSelectWidth |
| dropdownStyle | styles.popup.root |
| dropdownClassName / popupClassName | classNames.popup.root |
| dropdownRender | popupRender |
| onDropdownVisibleChange | onOpenChange |
| dataSource | options |
对于dataSource,源码还保留了向后兼容的转换逻辑(第 148~177 行):字符串会被转换为<Option value={item}>{item}</Option>,{ value, text }对象则以text作为选项展示文本。新代码建议直接使用options。
showSearch
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| filterOption | 是否根据输入项进行筛选。函数形式接收inputValue、option,符合筛选条件返回 true | boolean | function(inputValue, option) | true | |
| onSearch | 搜索补全项的时候调用 | function(value) | - |
类型定义上(AutoComplete.tsx 第 91~96 行),showSearch除了boolean外,可传入SearchConfig中filterOption、onSearch、searchIcon三个字段,与 demo 中showSearch={{ onSearch: ... }}的写法完全对应。
方法
通过ref获取实例后可调用:
| 名称 | 描述 |
|---|---|
| blur() | 移除焦点 |
| focus() | 获取焦点 |
由于组件类型签名为React.RefAttributes<BaseSelectRef>(AutoComplete.tsx 第 291~301 行),其 ref 实际是 Select 的BaseSelectRef,因此 Select ref 上的常用能力同样可用。
Semantic DOM 与语义化样式
classNames与styles支持的语义节点定义在 AutoComplete.tsx 第 23~40 行 的AutoCompleteSemanticType:
root:组件根节点,自动附加{prefixCls}-auto-complete类,使用自定义输入组件时还会附加{prefixCls}-customize类;prefix:前缀区域;input:输入框;placeholder:占位符;content:内容区;popup.root/popup.list/popup.listItem:下拉层及其内部列表、列表项。
其中popup.root会合并旧版popupClassName、dropdownClassName(见 finalClassNames 逻辑),这正是“旧属性迁移到classNames.popup.root”得以平滑过渡的实现细节。完整节点示例可参考 _semantic.tsx demo。
主题变量(Design Token)
AutoComplete 复用 Select 的设计 Token,配置方式与 Select 组件 相同,通过ConfigProvider的theme.components.Select调整。Token 明细请直接查阅文档中的 Select Token 表(原文档以<ComponentTokenTable component="Select">渲染),仓库中相关 Token 生成脚本见 generate-token-meta.ts。
FAQ
为何受控状态下使用 onSearch 无法输入中文?
请使用onChange进行受控管理。onSearch触发于搜索输入,与onChange时机不同。此外,点击选项时也不会触发onSearch事件。中文输入走 IME 组合事件,onSearch的组合(composition)期间不触发,导致受控值无法随拼音输入更新,而onChange的处理时机覆盖了这一过程。
为何 options 为空时,受控 open 展开不会显示下拉菜单?
AutoComplete 组件本质上是 Input 输入框的一种扩展,当options为空时,显示空文本会让用户误以为该组件不可操作,实际上它仍然可以进行文本输入操作。因此,为了避免给用户带来困惑,当options为空时,open属性为true也不会展示下拉菜单,需要与options属性配合使用。
小结
AutoComplete 在 ant-design 中的实现策略可以概括为:API 面向输入框心智,实现复用 Select 的 combobox 能力。掌握三个要点即可驾驭该组件:一是用showSearch(而非已废弃的顶层filterOption/onSearch)控制筛选与搜索回调;二是优先用options数据化配置替代 jsx children 和dataSource,以换取渲染性能和更好的维护性;三是通过classNames/styles的语义节点精确介入外观,替代零散的dropdownClassName等旧属性。遇到行为疑点时,可直接对照 AutoComplete 源码 与 Select 源码 中的属性合并逻辑快速定位。
【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/GitHub_Trending/an/ant-design
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考