输入框里的智能:用 Svelte 给搜索加实时联想

举报
静水流深-云海 发表于 2026/09/23 14:25:10 2026/09/23
【摘要】 用Svelte的响应式特性做一个带防抖的实时搜索联想框,输入即过滤、下拉即建议。

搜索框下面的联想词,看着像个大厂才有的功能,其实自己写起来意外地简单。最近我把博客里的标签筛选换成了一个实时联想输入框,用的是 Svelte——它没有虚拟 DOM 那一套,响应式靠编译器在编译期就处理好了,写一个"输入即出建议"的交互特别顺手。这篇就把最小可跑的版本拆给你看。

image.png

一、先想清楚要做什么

我们要的效果就三点:

  1. 用户在输入框敲字,不立刻查,停 300 毫秒再动(防抖);
  2. 从一份本地词表里过滤出包含关键字的项;
  3. 把结果渲染成下拉列表,点一下填回输入框。

如果是几百条以内的词表,根本不需要请求后端,前端过滤就够了,体验还更快。

二、Svelte 的响应式刚好够用

Svelte 里变量赋值本身就是响应式的,配上下拉渲染,几行就完事:

<script>
  let keyword = '';
  let suggestions = [];
  let timer;

  const words = ['svelte', 'spring', 'springboot', 'sql', 'svg', 'systemd', 'sse'];

  function onInput() {
    clearTimeout(timer);
    timer = setTimeout(() => {
      const k = keyword.trim().toLowerCase();
      suggestions = k
        ? words.filter(w => w.includes(k))
        : [];
    }, 300);
  }

  function pick(w) {
    keyword = w;
    suggestions = [];
  }
</script>

<input value={keyword} on:input={onInput} placeholder="搜点什么…" />
{#if suggestions.length}
  <ul>
    {#each suggestions as s}
      <li on:click={() => pick(s)}>{s}</li>
    {/each}
  </ul>
{/if}

关键点就两个:clearTimeout + setTimeout 做防抖,{#each} 直接把数组渲染成列表。Svelte 在编译时把这些绑定都接好了,不用你手动操作 DOM。

三、几种过滤方式的差别

方式 数据量 是否要后端 体验
前端 includes 过滤 几百条内 否 最快,零延迟
前端模糊匹配(正则) 几千条 否 灵活,需控制正则
后端接口搜索 海量 是 最准,但多一次网络

小词表直接前端过滤,别一上来就调接口,那是过度设计。

四、几个注意点

  • 防抖别省:每次按键都过滤,词表稍大就会卡,300ms 是手感和安全性的平衡点。
  • 空输入要还列表:keyword 清空时记得把 suggestions 置空,不然旧建议还挂着。
  • 点选后收起:选中一项就把 suggestions 清空,否则下拉一直挡着。

写在最后

实时联想这个东西,难点从来不在"怎么显示",而在"什么时候查、查多频繁"。把防抖和前端过滤这两道关过了,Svelte 写起来基本就是声明数据、声明渲染,剩下的编译器替你干。词表再大一点,把 filter 换成一次后端请求也只是在 onInput 里换个实现,结构不用动。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。