文章导读

  • 搜索页最难的不是画输入框,而是让结果在多数据源前提下仍然稳定、可信。
  • 羽球联盟把资讯和装备分成两个结果 Tab,但候选池的合并、去重和排序逻辑是统一的。
  • 远程数据负责新鲜度,本地数据负责完整度,顺序一旦反了,搜索页就会变得很奇怪。

页面效果

很多内容型应用都有一个共同问题:搜索框看上去已经做完了,但用户一搜就觉得“不对劲”。有时明明首页出现过的内容搜不到,有时同一条资讯在结果里重复出现,有时清空关键词后页面还停留在上一轮结果。这些都不是输入框的问题,而是结果组织的问题。

搜索结果页效果

羽球联盟搜索页的处理比较扎实。顶部先告诉用户当前命中了多少条资讯、多少条装备,正文再用 SegmentTab 把两类结果拆开。这样用户不会在一个长列表里混着看资讯卡片和装备卡片,也能快速判断自己这次搜的是“内容”还是“商品信息”。

实战拆解

这页真正的关键,在于搜索不是直接对某个数组 filter() 一下,而是先构造稳定候选池。资讯走 allArticles(),装备走 allEquipments()。如果远程数据为空,就直接退回本地静态数据;如果远程数据已经存在,就先放远程内容,再把本地里未被覆盖的条目补上。这样做的目的非常明确:搜索结果必须和首页刷新后的内容保持一致,但又不能因为远程源不完整而漏掉本地内容。

这里的顺序不能随便换。假如先放本地、后放远程,结果页就会把旧内容顶在前面,读者刚在首页看到的新资讯反而要往后翻;假如完全信任远程源,又会出现远程没有覆盖到的装备或资讯直接消失。羽球联盟实际上是在“新鲜度优先”和“完整度优先”之间做了一个对搜索体验更友好的平衡。

另一个容易被低估的点是命中字段。资讯侧不仅搜标题,还搜摘要、标签和作者;装备侧除了名称,还搜品牌、摘要和标签。真实用户很少会完整记住文章标题,他们更可能记得“某个品牌”“某个球员名”或者“某个装备关键词”。字段覆盖越接近用户记忆方式,搜索页越像真功能。

最后是空态。关键词为空时,页面明确提示“请输入关键词开始搜索”;关键词存在但没有命中时,又给出“没有找到相关资讯/装备”。这两个状态看起来只是文案差异,实际决定了用户能不能判断当前是“还没搜”还是“搜不到”。

关键代码

private allArticles(): Article[] {
  if (this.remoteArticles.length === 0) {
    return ARTICLES;
  }
  const remoteIds: Set<string> = new Set();
  for (const a of this.remoteArticles) {
    remoteIds.add(a.id);
  }
  const merged: Article[] = [];
  for (const a of this.remoteArticles) {
    merged.push(a);
  }
  for (const a of ARTICLES) {
    if (!remoteIds.has(a.id)) {
      merged.push(a);
    }
  }
  return merged;
}

private matchedArticles(): Article[] {
  const kw: string = this.keyword.trim().toLowerCase();
  return this.allArticles().filter((a: Article) => {
    const title: string = (a.title ?? '').toLowerCase();
    const summary: string = (a.summary ?? '').toLowerCase();
    const tag: string = (a.tag ?? '').toLowerCase();
    const author: string = (a.author ?? '').toLowerCase();
    return title.indexOf(kw) >= 0 || summary.indexOf(kw) >= 0
      || tag.indexOf(kw) >= 0 || author.indexOf(kw) >= 0;
  });
}

这段代码把搜索页最核心的判断顺序固定下来了:先合并,再去重,最后匹配。页面层不需要知道某条内容来自本地还是远程,只需要拿到一个稳定、可搜索的候选池。后面如果继续扩展赛事搜索或球员搜索,也能沿着同一套方法往下加。

设计落点

  • 搜索结果的可信度,首先来自候选池是否稳定,而不是搜索框本身好不好看。
  • 远程数据适合放在前面承接时效性,本地数据适合放在后面兜底完整度。
  • 搜索字段要贴近用户真实记忆方式,不能只盯着标题。

易踩坑

  • 不要先 filter() 再合并数据源,否则远程和本地之间的重复项很难收拾。
  • 不要只搜标题,很多真实检索都会落在品牌、标签、摘要或作者上。
  • 不要把“未输入关键词”和“没有命中结果”混成同一种空态,用户会很迷惑。

验证方式

  • 输入球员名、赛事名或装备品牌,确认资讯 Tab 和装备 Tab 都能返回对应结果。
  • 在首页刷新出新资讯后立即进入搜索页,确认新内容可以被搜到且排在前面。
  • 输入一个不存在的关键词,确认页面给出的是明确的无结果反馈,而不是空白列表。
  • 清空搜索词后重新观察页面,确认它回到提示态,而不是残留上一轮结果。

参考资料

小结

第 12 篇真正想说明的,不是搜索框怎么摆,而是搜索结果如何在多数据源前提下依然保持清晰、稳定和可预期。只要候选池的合并顺序和命中字段设计正确,搜索页就会从“能搜”变成“值得用”。

Logo

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

更多推荐