首页
/ ant-design AutoComplete 自动完成组件深度解析:从 API 全量参数到 Select Combobox 底层实现

ant-design AutoComplete 自动完成组件深度解析:从 API 全量参数到 Select Combobox 底层实现

2026-09-06 12:27:33作者:范靓好Udolf

本文基于 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 支持 labelvalue 分离的数据化配置,相比 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 时,才会被识别为自定义输入组件,并通过内部 API getInputElement 透传给 Select。同时源码在开发环境下有一条 warning:使用自定义输入组件时不应再设置 size,需要自行控制尺寸样式。

4. 不区分大小写:showSearch.filterOption

筛选逻辑挂在 showSearch.filterOption 上,函数接收 inputValueoption 两个参数(见 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()),
  }}
/>

需要特别注意:顶层的 filterOptiononSearchdataSource 等均已废弃(见下文 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 精确定位 rootinputpopup 等语义节点。

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> -
dataSource 自动完成的数据源,请使用 options 替代 DataSourceItemType[] - -
defaultActiveFirstOption 是否默认高亮第一个选项 boolean true
defaultOpen 是否默认展开下拉菜单 boolean -
defaultValue 指定默认选中的条目 string -
disabled 是否禁用 boolean false
dropdownClassName 下拉菜单的 className 属性,请使用 classNames.popup.root 替代 string - -
dropdownMatchSelectWidth 下拉菜单和输入框是否同宽,请使用 popupMatchSelectWidth 替代 boolean | number true -
dropdownRender 自定义下拉框内容,使用 popupRender 替换 (originNode: ReactElement) => ReactNode - 4.24.0
popupRender 自定义下拉框内容 (originNode: ReactElement) => ReactNode -
popupClassName 下拉菜单的 className 属性,使用 classNames.popup.root 替换 string - 4.23.0
dropdownStyle 下拉菜单的 style 属性,使用 styles.popup.root 替换 CSSProperties -
popupMatchSelectWidth 下拉菜单和选择器同宽。默认将设置 min-width,当值小于选择框宽度时会被忽略。false 时会关闭虚拟滚动 boolean | number true
filterOption 是否根据输入项进行筛选。当其为一个函数时,会接收 inputValueoption 两个参数 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) -
onDropdownVisibleChange 展开下拉菜单的回调,使用 onOpenChange 替换 (open: boolean) => void
onOpenChange 展开下拉菜单的回调 (open: boolean) => void -
onFocus 获得焦点时的回调 function() -
onSearch 搜索补全项的时候调用 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 是否根据输入项进行筛选。函数形式接收 inputValueoption,符合筛选条件返回 true boolean | function(inputValue, option) true
onSearch 搜索补全项的时候调用 function(value) -

类型定义上(AutoComplete.tsx 第 91~96 行),showSearch 除了 boolean 外,可传入 SearchConfigfilterOptiononSearchsearchIcon 三个字段,与 demo 中 showSearch={{ onSearch: ... }} 的写法完全对应。

方法

通过 ref 获取实例后可调用:

名称 描述
blur() 移除焦点
focus() 获取焦点

由于组件类型签名为 React.RefAttributes<BaseSelectRef>AutoComplete.tsx 第 291~301 行),其 ref 实际是 Select 的 BaseSelectRef,因此 Select ref 上的常用能力同样可用。

Semantic DOM 与语义化样式

classNamesstyles 支持的语义节点定义在 AutoComplete.tsx 第 23~40 行AutoCompleteSemanticType

  • root:组件根节点,自动附加 {prefixCls}-auto-complete 类,使用自定义输入组件时还会附加 {prefixCls}-customize 类;
  • prefix:前缀区域;
  • input:输入框;
  • placeholder:占位符;
  • content:内容区;
  • popup.root / popup.list / popup.listItem:下拉层及其内部列表、列表项。

其中 popup.root 会合并旧版 popupClassNamedropdownClassName(见 finalClassNames 逻辑),这正是“旧属性迁移到 classNames.popup.root”得以平滑过渡的实现细节。完整节点示例可参考 _semantic.tsx demo。

主题变量(Design Token)

AutoComplete 复用 Select 的设计 Token,配置方式与 Select 组件 相同,通过 ConfigProvidertheme.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 源码 中的属性合并逻辑快速定位。

登录后查看全文
热门项目推荐
相关项目推荐