一张适合文章开头的手绘笔记风框架图,主题是 HarmonyOS 7 端侧搜索的小型索引。画面中心是一

前言

端侧搜索适合小数据、高频输入的场景。联系人、功能入口、城市列表这类内容,如果每敲一个字都请求网络,体验反而会被抖动拖慢。

这篇单独聊 联系人搜索 这个场景。重点不是堆 API,而是为小数据量建立端侧索引,让高频输入时列表即时响应。

为什么这个问题经常被写乱

端侧搜索的小型索引 这类内容很容易被写成“代码能跑就算讲完了”,但对初学者来说,这恰恰是最不够的地方。真正让人卡住的,往往不是某个组件名记不住,而是不知道这段代码为什么要这样拆、状态为什么要这样放、以后需求变化时应该从哪里改。

所以这篇文章不只想给你一个能跑的例子,更想把背后的判断过程讲清楚。你只要把这个判断过程吃透,后面自己改页面、补需求、查问题时,心里会稳很多。

一张手绘流程图,内容是“端侧搜索小型索引的实操步骤”。按文章步骤画成四步流程:1 原始数据保留 `n

小型索引适合本地数据

联系人、城市、常用功能入口这类数据量不大,没必要每输入一个字就请求服务端。端侧先建一个简单索引,体验会顺很多,也能减少网络抖动带来的空白。

实操步骤
  1. 原始数据保留 name/phone/keyword
  2. 初始化时生成 searchText,把可搜索字段拼在一起。
  3. 输入变化时只过滤索引字段。
  4. 没有结果时显示空状态,不让列表直接消失。
数据量 推荐方式
100 条以内 直接 filter
1000 条以内 预建小索引
更大数据 分页或后端搜索

端侧搜索不是替代后端搜索,而是解决“小数据、高频输入”的响应速度问题。

interface ContactItem {
  id: number
  name: string
  phone: string
  keyword: string
}

interface ContactIndex {
  id: number
  name: string
  phone: string
  searchText: string
}

@Entry
@Component
struct LocalSearchPage {
  @State query: string = ''
  private contacts: ContactIndex[] = [
    { id: 1, name: '陈安', phone: '13800001111', searchText: '陈安 chen an 13800001111' },
    { id: 2, name: '李北桥', phone: '13900002222', searchText: '李北桥 li bei qiao 13900002222' },
    { id: 3, name: '王小满', phone: '13700003333', searchText: '王小满 wang xiao man 13700003333' }
  ]

  private result(): ContactIndex[] {
    const text = this.query.trim().toLowerCase()
    if (text.length === 0) {
      return this.contacts
    }
    return this.contacts.filter((item: ContactIndex) => item.searchText.toLowerCase().indexOf(text) >= 0)
  }

  build() {
    Column({ space: 12 }) {
      Text('联系人搜索').fontSize(22).fontWeight(FontWeight.Bold)
      TextInput({ placeholder: '搜索姓名、拼音或手机号', text: this.query }).onChange((value: string) => this.query = value)

      if (this.result().length === 0) {
        Text('没有找到匹配联系人').fontSize(14).fontColor('#888888').padding(20)
      } else {
        List({ space: 8 }) {
          ForEach(this.result(), (item: ContactIndex) => {
            ListItem() {
              Row() {
                Column({ space: 4 }) {
                  Text(item.name).fontSize(16).fontWeight(FontWeight.Medium)
                  Text(item.phone).fontSize(12).fontColor('#777777')
                }.alignItems(HorizontalAlign.Start)
                Blank()
                Button('拨打').height(30).fontSize(12)
              }.padding(12).backgroundColor('#FFFFFF').borderRadius(8)
            }
          }, (item: ContactIndex) => item.id.toString())
        }.layoutWeight(1)
      }
    }.padding(16).height('100%').backgroundColor('#F5F7FA')
  }
}

一张用于解释代码核心逻辑的手绘信息图,主题是 HarmonyOS 7 ArkTS 联系人搜索示例。画

把关键代码一段段拆开
  • searchText 把姓名、拼音、手机号合并,过滤时只查一个字段。
  • result() 对空输入直接返回完整列表,避免写两套列表 UI。
  • 空结果单独展示文案,用户知道不是页面坏了。
  • query 是唯一输入状态,搜索结果不额外保存,避免不同步。
端侧搜索不要额外存一份结果

小数据端侧搜索里,query 通常就是唯一输入状态,搜索结果可以通过 result() 派生出来。额外保存一份 searchResult,看起来能少算几次,实际很容易和原始数据不同步。

示例把姓名、拼音和手机号提前合成 searchText,输入变化时只过滤这个字段。空输入返回全量联系人,无结果时显示空状态,用户能明确知道是没有匹配项,而不是列表坏了。

写在最后

数据量继续变大时,不要硬扛本地过滤。几百条以内端侧索引很舒服,更多数据就要考虑分页、后端搜索或更专业的索引结构。搜索方案要跟数据量匹配,不能只看当前 mock 数据很顺。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐