HarmonyOS7 端侧搜索的小型索引:ArkUI/ArkTS 实战拆解
·

前言
端侧搜索适合小数据、高频输入的场景。联系人、功能入口、城市列表这类内容,如果每敲一个字都请求网络,体验反而会被抖动拖慢。
这篇单独聊 联系人搜索 这个场景。重点不是堆 API,而是为小数据量建立端侧索引,让高频输入时列表即时响应。
为什么这个问题经常被写乱
端侧搜索的小型索引 这类内容很容易被写成“代码能跑就算讲完了”,但对初学者来说,这恰恰是最不够的地方。真正让人卡住的,往往不是某个组件名记不住,而是不知道这段代码为什么要这样拆、状态为什么要这样放、以后需求变化时应该从哪里改。
所以这篇文章不只想给你一个能跑的例子,更想把背后的判断过程讲清楚。你只要把这个判断过程吃透,后面自己改页面、补需求、查问题时,心里会稳很多。

小型索引适合本地数据
联系人、城市、常用功能入口这类数据量不大,没必要每输入一个字就请求服务端。端侧先建一个简单索引,体验会顺很多,也能减少网络抖动带来的空白。
实操步骤
- 原始数据保留
name/phone/keyword。 - 初始化时生成
searchText,把可搜索字段拼在一起。 - 输入变化时只过滤索引字段。
- 没有结果时显示空状态,不让列表直接消失。
| 数据量 | 推荐方式 |
|---|---|
| 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')
}
}

把关键代码一段段拆开
searchText把姓名、拼音、手机号合并,过滤时只查一个字段。result()对空输入直接返回完整列表,避免写两套列表 UI。- 空结果单独展示文案,用户知道不是页面坏了。
query是唯一输入状态,搜索结果不额外保存,避免不同步。
端侧搜索不要额外存一份结果
小数据端侧搜索里,query 通常就是唯一输入状态,搜索结果可以通过 result() 派生出来。额外保存一份 searchResult,看起来能少算几次,实际很容易和原始数据不同步。
示例把姓名、拼音和手机号提前合成 searchText,输入变化时只过滤这个字段。空输入返回全量联系人,无结果时显示空状态,用户能明确知道是没有匹配项,而不是列表坏了。
写在最后
数据量继续变大时,不要硬扛本地过滤。几百条以内端侧索引很舒服,更多数据就要考虑分页、后端搜索或更专业的索引结构。搜索方案要跟数据量匹配,不能只看当前 mock 数据很顺。
更多推荐


所有评论(0)