Ant Design AutoComplete「查询模式:确定类目」实战指南:分组选项与下拉样式定制
【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/gh_mirrors/ant/ant-design
导读
本篇围绕 Ant Design AutoComplete 组件的经典演示「查询模式:确定类目(Certain Category)」展开,该演示是交互规范文档中"自动完成"查询模式(Lookup Patterns)在组件层面的标准实现:用户输入关键词后,下拉列表按"Libraries / Solutions / Articles"等固定类目分组展示匹配项。读完本文,你将掌握 AutoComplete 分组选项(options+label+options嵌套结构)的完整写法、下拉菜单样式定制(popupClassName与配套 CSS)、与"不确定类目"场景的取舍,以及相关 API 的源码级行为。
一、什么是"确定类目"查询模式
在 Ant Design 交互规范中,自动完成组件用于"用户输入时,下拉列表随着输入的关键词显示匹配项"。根据查询结果分类的多少,规范将其划分为两种类型:
- 确定类目(Certain Category):用户所查询的关键词,只会出现在若干固定类目中(例如"话题""问题""文章"3 种类目),下拉列表按这些类目分组渲染;
- 不确定类目(Uncertain Category):用户所查询的关键词所属类目数量不确定,可能 4 个、可能 5 个,甚至更多,下拉列表通常按"匹配结果"平铺渲染。
本演示即前者的实现样例,对应演示入口位于 certain-category.tsx,其文档说明位于 certain-category.md。与它形成对照的"不确定类目"样例可参考 uncertain-category.tsx。
提示:本文所有代码路径均以仓库根目录为基准,可打开对应文件直接查看完整源码。
二、分组选项的数据结构:options的嵌套写法
"确定类目"的核心在于把下拉选项按类目分组。AutoComplete 直接复用了 Select 的options数据化配置协议——当某个选项对象同时包含label与options两个字段时,它就是一个分组(Group),而不是普通选项。
看演示中的完整数据定义(certain-category.tsx):
const renderItem = (title: string, count: number) => ({ value: title, label: ( <Flex align="center" justify="space-between"> {title} <span> <UserOutlined /> {count} </span> </Flex> ), }); 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)], }, { label: <Title title="Articles" />, options: [renderItem('AntDesign design language', 100000)], }, ];要点拆解:
- 顶层数组的每个元素代表一个类目,其中
label是类目标题(Group Title),options是该类目下的子项数组; - 子项对象由
value(选中时回填/回调的取值)与label(下拉中渲染的内容)组成,label可以是任意 ReactNode,因此可以像演示中那样内嵌图标与数字统计; - 官方文档对
options的说明是"数据化配置选项内容,相比 jsx 定义会获得更好的渲染性能",类型为{ label, value }[](见 auto-complete/index.zh-CN.md),这里的分组结构正是该数据协议的自然扩展。
类目标题的自定义渲染
演示中类目标题本身也是自定义 ReactNode,由Title组件渲染(certain-category.tsx):
const Title: React.FC<Readonly<{ title?: string }>> = (props) => ( <Flex align="center" justify="space-between"> {props.title} <a href="https://www.google.com/search?q=antd" target="_blank" rel="noopener noreferrer"> more </a> </Flex> );每个类目标题右侧都有一个"more"跳转链接,这是"确定类目"模式的常见产品交互:类目是已知的、稳定的,因此可以直接引导用户进入该分类的更多结果页。
分组协议在 Select 层面的等价写法
如果偏好 JSX 写法,同样的分组效果可以用OptGroup实现(参见 select/demo/optgroup.tsx 对应示例)。OptGroup的label属性即分组标题,其下通过Select.Option声明子项。AutoComplete 内部本质上是 Select 的一个"无后缀图标、自由输入"的变体(详见本文第五节),因此两种数据协议均可用;options对象写法因免去 JSX 实例化开销而性能更优。
三、完整的 AutoComplete 装配与下拉样式定制
组件装配
const App: React.FC = () => ( <AutoComplete popupClassName="certain-category-search-dropdown" popupMatchSelectWidth={500} style={{ width: 250 }} options={options} size="large" > <Input.Search size="large" placeholder="input here" /> </AutoComplete> );这里涉及几个与本场景强相关的 API(完整 API 表见 auto-complete/index.zh-CN.md):
| 参数 | 说明 | 本示例取值 |
|---|---|---|
options | 数据化配置选项内容 | 分组后的选项数组 |
popupClassName | 下拉菜单的 className,用于精准定位样式作用域(4.23.0 起,替代已废弃的dropdownClassName) | "certain-category-search-dropdown" |
popupMatchSelectWidth | 下拉菜单与输入框同宽。默认设置min-width,当值小于选择框宽度时会被忽略;false会关闭虚拟滚动 | 500(固定下拉宽度) |
size | 尺寸 | large |
style | 作用于输入框容器的内联样式 | { width: 250 } |
注意:当通过children传入自定义输入组件(如这里的Input.Search)时,组件源码会给出开发期警告——"You need to control style self instead of settingsizewhen using customize input",即尺寸应交给自定义输入框自身控制,而不是同时给 AutoComplete 设置size(见 index.tsx)。因此更严谨的写法是仅在Input.Search上声明size="large",演示中同时设置属于宽松写法,实际项目建议遵循该警告收敛到一处。
下拉菜单样式定制(CSS 逐段解析)
原文档给出了配套的样式文件(certain-category.md),作用域全部挂在popupClassName指定的类名之下,逐段含义如下:
/* 类目分组标题:置灰加粗,弱化标题、突出子项 */ .certain-category-search-dropdown .ant-select-dropdown-menu-item-group-title { color: #666; font-weight: bold; } /* 类目分组之间用细分割线隔开,形成"确定类目"的区块感 */ .certain-category-search-dropdown .ant-select-dropdown-menu-item-group { border-bottom: 1px solid #f6f6f6; } /* 子项默认左缩进 16px,与类目标题产生视觉层级 */ .certain-category-search-dropdown .ant-select-dropdown-menu-item { padding-inline-start: 16px; } /* 预留的 "show-all" 类:用于"查看全部"这类居中的特殊项(本例未启用) */ .certain-category-search-dropdown .ant-select-dropdown-menu-item.show-all { text-align: center; cursor: default; } /* 下拉菜单整体限高 300px,超出滚动 */ .certain-category-search-dropdown .ant-select-dropdown-menu { max-height: 300px; }三个可复用的设计手法:
- 用
popupClassName做样式作用域,避免全局污染其他下拉;若项目使用 CSS-in-JS(如 antd 官方推荐的@ant-design/cssinjs方案),也可在dropdownRender或主题 Token 层面实现等价定制; - 分组标题 + 子项缩进 + 分割线三个要素叠加,是"确定类目"分组视觉的通用配方;
- 限高 + 内部滚动(
max-height)保证类目较多时下拉不至于撑满视口。
样式选择器中的
.ant-select-dropdown-menu系列类名对应 rc-select 内部 DOM 结构,antd 版本升级时若类名变更需同步调整;更稳妥的方式是优先使用 antd 官方文档维护的语义化 API(popupClassName结合组件文档推荐的 Token)。
四、与"不确定类目"模式的对比
将 uncertain-category.tsx 与本文演示对比,能清晰看出两种模式的分工:
| 维度 | 确定类目(本演示) | 不确定类目 |
|---|---|---|
| 选项结构 | 固定分组:label(类目标题)+options(子项) | 平铺:value+label |
| 数据来源 | 静态/预定义,类目稳定 | 随onSearch动态生成(如searchResult(query)模拟远程搜索) |
| 交互特征 | 类目可点击跳转"更多" | 每条结果展示命中位置与结果数(如 "Found xx on …") |
| 关键事件 | 侧重展示与选择 | 依赖onSearch驱动setOptions刷新候选 |
不确定类目演示还示范了受控options的典型写法:onSearch触发时根据输入值生成候选并setOptions,空输入时置空数组(uncertain-category.tsx),适合类目数量不可预知的搜索建议场景。
五、源码级原理:AutoComplete 如何驱动分组下拉
AutoComplete 的入口实现揭示了它和 Select 的关系:
- 本质是 Select 的封装:AutoComplete 将自身
prefixCls设为 Select 的getPrefixCls('select', customizePrefixCls),并向内部 Select 透传popupClassName、dropdownStyle等属性,同时强制mode={Select.SECRET_COMBOBOX_MODE_DO_NOT_USE}并设置suffixIcon={null}——这正是"自由输入、不强制选择"行为的来源(index.tsx); - 选项协议归一:
options直接透传给内部 Select,分组结构(label+options)由 rc-select 的分组渲染逻辑消费;而旧的dataSourceprop 会在内部被转换为Option子节点(index.tsx),且源码通过warning.deprecated提示"请改用options"(index.tsx); - 分组字段可自定义:Select 的
fieldNames支持自定义label / value / options / groupLabel字段名(groupLabel自 5.6.0 起,见 select/index.en-US.md),AutoComplete 同样继承该能力,当后端返回的分组字段名不是label/options时无需改写数据结构; - 下拉样式作用域:
popupClassName最终作为内部 Select 下拉菜单的 className 挂载,因此文档中的 CSS 全部以它为前缀书写;同时 AutoComplete 还会通过useZIndex为dropdownStyle补充层级 zIndex,避免弹层被遮挡(index.tsx)。
关于筛选的默认行为
AutoComplete 文档中filterOption默认值为true(见 auto-complete/index.zh-CN.md),即默认按输入值对选项做过滤。若希望"确定类目"下输入时不过滤、始终展示全部分组(类似演示中数据源较短、希望看到全貌的场景),可显式设置filterOption={false}或传入自定义过滤函数(inputValue, option) => boolean。
已知边界:options 为空时受控 open 不展开
组件 FAQ 明确说明:AutoComplete 本质是 Input 的扩展,当options为空时即便open={true}也不会显示下拉菜单,以避免用户误以为组件不可操作;open必须与options配合使用(见 auto-complete/index.zh-CN.md)。在设计"确定类目"的空态交互时需留意此行为,例如可配合notFoundContent定制空列表提示。
六、将演示改造为可运行的完整示例
将上述内容整合为可直接运行的最小示例(在支持 React + antd 的环境下,引入后挂载渲染即可):
import React from 'react'; import { UserOutlined } from '@ant-design/icons'; import { AutoComplete, Flex, Input } from 'antd'; const renderItem = (title: string, count: number) => ({ value: title, label: ( <Flex align="center" justify="space-between"> {title} <span> <UserOutlined /> {count} </span> </Flex> ), }); const options = [ { label: 'Libraries', options: [renderItem('AntDesign', 10000), renderItem('AntDesign UI', 10600)], }, { label: 'Solutions', options: [renderItem('AntDesign UI FAQ', 60100), renderItem('AntDesign FAQ', 30010)], }, ]; export default () => ( <AutoComplete popupClassName="certain-category-search-dropdown" popupMatchSelectWidth={500} style={{ width: 250 }} options={options} > <Input.Search size="large" placeholder="input here" /> </AutoComplete> );配套 CSS 直接沿用原文档的样式块(见第二节 CSS 片段)即可获得分组标题加粗、分割线、子项缩进与 300px 限高的完整效果。
七、深入阅读
- 组件完整 API、方法与 FAQ:auto-complete/index.zh-CN.md
- 组件源码实现:auto-complete/index.tsx
- 演示源码与样式:certain-category.tsx、certain-category.md
- 不确定类目对照演示:uncertain-category.tsx
- 交互规范「查询模式」章节:reaction.zh-CN.md
- 单元测试(覆盖自定义输入、
dataSource对象数组、Option兼容、popupClassName等行为):auto-complete/tests/index.test.tsx
【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/gh_mirrors/ant/ant-design
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考