搜索是移动应用中最核心的导航方式之一。当内容超过用户一屏能浏览的范围时,搜索栏就成为用户最快找到目标内容的入口。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. 更灵活的外观控制(圆角搜索框 + 右侧搜索按钮)
  2. 可以自己管理清除按钮的显示逻辑
  3. 更容易扩展为带筛选标签的高级搜索

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;
  });
}

搜索范围涵盖三个字段:

  1. 标题匹配(最高优先级):用户输入"状态管理"直接命中标题
  2. 摘要匹配:用户输入"跨设备"命中摘要中的描述
  3. 分类匹配:用户输入"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);
}

搜索历史的逻辑有两个关键点:

  1. 去重:如果用户搜索了"状态管理",再次搜索"状态管理"时,旧记录被移除(避免重复出现)
  2. 头部插入:最近搜索的在最上面
  3. 上限 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 搜索场景的开发方法。核心知识点包括:

  1. Search 组件 vs TextInput:Search 开箱即用,TextInput 更灵活
  2. 实时过滤:onChange 回调 + filter + indexOf 多字段匹配
  3. 热门标签:可点击标签云 + 点击即搜 + 历史保存
  4. 搜索历史:去重 + 头部插入 + 上限控制 + 重新搜索刷新顺序
  5. 双视图切换:浏览模式(引导)vs 搜索模式(结果)
  6. onSubmit 参数类型:EnterKeyType 而非 string

搜索是移动应用中最值得投入设计精力的交互之一。一个好的搜索体验不是简单的"输入框 + 结果列表"——它需要热门标签引导无目标的浏览、搜索历史减少重复输入、实时过滤让用户边输入边看到反馈。ArkUI 的 Search 组件和 TextInput 组件提供了构建这些体验的基础设施,而搜索逻辑、数据结构和 UI 切换则是开发者需要精心设计的部分。


Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐