鸿蒙新特性:Search 搜索组件——构建知识库检索与智能过滤
搜索是移动应用中最核心的导航方式之一。当内容超过用户一屏能浏览的范围时,搜索栏就成为用户最快找到目标内容的入口。HarmonyOS NEXT ArkUI 提供了 Search 组件——一个开箱即用的搜索栏,但真正的搜索体验远远不止一个输入框:实时过滤、热门标签、搜索历史和结果高亮共同构成了完整的搜索交互。
本文将深入讲解 Search 组件与 TextInput 在搜索场景中的应用,并构建一个完整的"知识库搜索"应用——支持关键词实时过滤、热门标签点击即搜、搜索历史管理和多维度结果展示。
关键词:HarmonyOS、ArkUI、Search、搜索栏、实时过滤、知识库、搜索历史
一、Search 与 TextInput 的搜索场景
1.1 Search 组件 API
Search({ placeholder: '搜索文档...', value: this.query })
.searchIcon({ src: $r('sys.symbol.magnifyingglass') })
.onChange((value: string) => {
this.doSearch(value);
})
.onSubmit((value: string) => {
this.saveHistory(value);
})
核心属性:
- placeholder:占位提示文本
- value:搜索框的当前文本,通过
@State双向绑定 - searchIcon:搜索图标,可自定义资源
- onChange:输入内容变化时触发,用于实时搜索/过滤
- onSubmit:用户在键盘上按回车/搜索键时触发
1.2 Search vs TextInput
Search 组件本质上是一个定制化的 TextInput,增加了搜索图标和清除按钮。在灵活性方面,TextInput 更自由——可以完全自定义外观、按钮和行为:
Row() {
TextInput({ text: this.query, placeholder: '搜索文档...' })
.onChange((value: string) => { this.doSearch(value); })
.onSubmit((enterKey: EnterKeyType) => { this.saveHistory(this.query); })
Text('搜索')
}
本文 Demo 选择基于 TextInput 构建搜索体验,原因有三:
- 更灵活的外观控制(圆角搜索框 + 右侧搜索按钮)
- 可以自己管理清除按钮的显示逻辑
- 更容易扩展为带筛选标签的高级搜索
1.3 onSubmit 的参数类型
一个重要但容易被忽略的细节:TextInput 的 onSubmit 回调参数类型是 EnterKeyType(键盘上的回车键类型),而非输入框的文本值。如果需要在回车时获取当前文本,应直接引用 @State 变量:
// 正确
.onSubmit((enterKey: EnterKeyType) => {
this.saveHistory(this.query);
})
// 错误 —— 编译报错
.onSubmit((value: string) => {
this.saveHistory(value);
})
二、知识库搜索的整体设计
2.1 页面架构
本文 Demo 构建一个"知识库搜索"应用,模拟技术文档库的搜索体验:
SearchPage
├── 标题栏 — "知识库搜索" + 文档总数
├── 搜索栏 — TextInput + 清除按钮 + 搜索按钮
├── 搜索前视图(query 为空时)
│ ├── 组件说明卡片
│ ├── 热门搜索标签(可点击快速搜索)
│ └── 搜索历史列表(可清空)
└── 搜索结果视图(query 非空时)
├── 结果计数
└── 文档卡片列表(标题 + 分类 + 摘要 + 标签)
2.2 数据结构
interface ArticleItem {
id: number;
title: string;
category: string; // 分类(ArkUI / 分布式 / 性能 / ...)
summary: string; // 摘要
tags: string[]; // 标签列表
}
10 篇预设文档覆盖了 ArkUI、分布式、性能、安全、多媒体、网络、工具等分类。每篇文档的标题、摘要和标签都是搜索的目标字段——用户在搜索框输入的关键词会在这三个字段中匹配。
2.3 搜索逻辑
doSearch(q: string): void {
this.query = q;
if (q.trim().length === 0) {
this.results = [];
this.showResults = false;
return; // 空搜索 → 回到初始状态
}
this.showResults = true;
let keyword = q.trim().toLowerCase();
this.results = this.getArticles().filter((a: ArticleItem) => {
return a.title.toLowerCase().indexOf(keyword) >= 0 ||
a.summary.toLowerCase().indexOf(keyword) >= 0 ||
a.category.toLowerCase().indexOf(keyword) >= 0;
});
}
搜索范围涵盖三个字段:
- 标题匹配(最高优先级):用户输入"状态管理"直接命中标题
- 摘要匹配:用户输入"跨设备"命中摘要中的描述
- 分类匹配:用户输入"ArkUI"命中分类字段
大小写不敏感(toLowerCase())确保中英文混合输入时的一致性。空搜索直接返回初始状态(显示热门标签和历史),不展示空结果。
三、热门搜索标签
3.1 标签设计
热门搜索以标签云形式展示,每个标签可点击:
getHotTags(): string[] {
return ['状态管理', '性能优化', '自定义组件', '动画', '分布式', '网络请求'];
}
标签的视觉层次通过颜色和背景区分——前 3 个标签(最热门)使用蓝色背景,其余使用灰色背景。这给用户一个隐性的引导:蓝色标签是推荐点击的。
3.2 点击即搜
searchHot(tag: string): void {
this.doSearch(tag);
this.saveHistory(tag);
}
点击热门标签自动执行搜索并保存到历史。这意味着热门标签不仅是"推荐入口",也是"可记录的行为"——用户点击后,该关键词出现在历史列表中,方便下次直接使用。
四、搜索历史管理
4.1 去重 + 头部插入
saveHistory(q: string): void {
if (q.trim().length === 0) return;
let trimmed = q.trim();
// 去重:删除旧的出现
this.history = this.history.slice()
.filter((h: string) => h !== trimmed);
// 插入头部
this.history = [trimmed].concat(this.history.slice()).slice(0, 8);
}
搜索历史的逻辑有两个关键点:
- 去重:如果用户搜索了"状态管理",再次搜索"状态管理"时,旧记录被移除(避免重复出现)
- 头部插入:最近搜索的在最上面
- 上限 8 条:
slice(0, 8)限制历史记录数量,防止列表无限增长
4.2 历史查询与清空
// 点击历史记录直接搜索
searchFromHistory(h: string): void {
this.doSearch(h);
this.saveHistory(h);
}
// 一键清空
clearHistory(): void {
this.history = [];
}
点击历史记录重新搜索时,会再次调用 saveHistory——这会导致该记录被"刷新"到列表顶部(先删旧记录,再加到头部),保持了"最近使用优先"的顺序。
五、搜索结果展示
5.1 文档卡片
每条搜索结果以卡片形式展示:
┌──────────────────────────────┐
│ [ArkUI] 1. │
│ ArkUI 状态管理最佳实践 │
│ 深入理解装饰器的使用场景... │
│ #状态管理 #@State #性能 │
└──────────────────────────────┘
卡片包含:
- 分类标签(蓝色,左上角):快速识别文档领域
- 序号(灰色,右上角):视觉排序辅助
- 标题(黑色加粗):文档名称
- 摘要(灰色,最多 2 行):核心内容预览
- 标签(浅灰背景):技术关键词
5.2 空结果处理
当搜索无结果时,显示友好的空状态:
未找到相关文档
试试其他关键词
空结果不是空白页面——它告知用户"找到了 0 条结果",并提示"试试其他关键词"作为下一步行动引导。
5.3 结果计数
搜索结果顶部显示匹配数量:
搜索结果
共 5 条结果
这个数字随搜索输入实时变化,给用户即时反馈——“我的搜索词是缩小还是扩大了结果范围”。
六、页面状态切换
6.1 双视图模式
页面在两种模式间切换,由 showResults 状态控制:
- 浏览模式(
showResults = false):展示热门标签 + 搜索历史 + 组件说明 - 搜索模式(
showResults = true):展示搜索结果
切换条件:搜索框内容非空时进入搜索模式,清空后回到浏览模式。这种双视图设计遵循"渐进式信息披露"原则——用户不搜索时看到的是引导和推荐,开始搜索后才看到结果。
6.2 清除按钮
搜索框右侧的清除按钮(✕ 图标)仅在内容非空时显示:
if (this.query.length > 0) {
Text('✕')
.onClick(() => {
this.query = '';
this.results = [];
this.showResults = false;
})
}
点击清除后,同时清空查询文本、结果数组和搜索状态——一步回到初始界面。这个逻辑也适用于用户按键盘退格键直到内容为空(onChange 检测到空字符串时自动回到浏览模式)。
七、信息架构与文档预览
7.1 文档库设计
10 篇文档覆盖了鸿蒙开发的核心领域:
| 文档标题 | 分类 | 关键标签 |
|---|---|---|
| ArkUI 状态管理最佳实践 | ArkUI | 状态管理、@State、性能 |
| HarmonyOS 分布式数据管理 | 分布式 | 分布式、数据同步 |
| 鸿蒙原生应用性能优化指南 | 性能 | 性能、优化、布局 |
| ArkTS 异步编程与并发模型 | ArkTS | 异步、并发、TaskPool |
| HarmonyOS 安全开发规范 | 安全 | 安全、权限、加密 |
| ArkUI 自定义组件开发详解 | ArkUI | 组件、@Component |
| 鸿蒙多媒体开发指南 | 多媒体 | 音视频、相机、图像 |
| HarmonyOS 网络请求与数据缓存 | 网络 | HTTP、WebSocket |
| ArkUI 动画与交互设计 | ArkUI | 动画、转场、手势 |
| 鸿蒙应用测试与调试工具链 | 工具 | 测试、调试、DevEco |
这个文档库在 Demo 中是硬编码的数组,在真实应用中会从后端 API 或本地数据库加载。但搜索逻辑(filter + indexOf)是相同的。
7.2 搜索示例
用户输入"组件":
- 命中"自定义组件开发详解"(标题匹配)
- 命中"自定义 UI 组件库"(摘要匹配)
- 返回 1 条结果(仅标题匹配,摘要虽含"组件"但属于同一篇文档)
用户输入"性能":
- 命中"性能优化指南"(标题匹配)
- 命中"状态管理最佳实践"(摘要含"性能优化技巧")
- 返回 2 条结果
八、交互流程演示
8.1 浏览热门
进入页面,搜索框为空。浏览模式下展示 6 个热门标签,前 3 个为蓝色。"搜索历史"区域为空(首次使用)。
8.2 点击热门标签
点击"状态管理"标签。搜索框自动填入"状态管理",页面切换到搜索模式。结果区域显示匹配的文档(1 条)。“搜索历史"区域新增"状态管理”。
8.3 手动输入搜索
点击搜索框,输入"动画"。搜索结果实时过滤,显示"ArkUI 动画与交互设计"文档。按回车,搜索历史新增"动画"。
8.4 查看历史
清空搜索框,回到浏览模式。搜索历史显示两条记录("动画"在上,"状态管理"在下)。点击"状态管理"快速重新搜索。
8.5 清空历史
点击"清空"按钮,搜索历史被清除。
九、总结
本文通过"知识库搜索"这个实战案例,全面讲解了 ArkUI 搜索场景的开发方法。核心知识点包括:
- Search 组件 vs TextInput:Search 开箱即用,TextInput 更灵活
- 实时过滤:onChange 回调 + filter + indexOf 多字段匹配
- 热门标签:可点击标签云 + 点击即搜 + 历史保存
- 搜索历史:去重 + 头部插入 + 上限控制 + 重新搜索刷新顺序
- 双视图切换:浏览模式(引导)vs 搜索模式(结果)
- onSubmit 参数类型:EnterKeyType 而非 string
搜索是移动应用中最值得投入设计精力的交互之一。一个好的搜索体验不是简单的"输入框 + 结果列表"——它需要热门标签引导无目标的浏览、搜索历史减少重复输入、实时过滤让用户边输入边看到反馈。ArkUI 的 Search 组件和 TextInput 组件提供了构建这些体验的基础设施,而搜索逻辑、数据结构和 UI 切换则是开发者需要精心设计的部分。
更多推荐



所有评论(0)