input事件监听+文本匹配是最直接起点,需大小写不敏感、空字符串显示全部、缓存DOM、正则高亮防转义、必加防抖、无结果时动态提示、区分数据为空与搜索无结果。

input 事件监听 + 文本匹配是最直接的起点
直接用 input 事件监听搜索框,比 change 或 keyup 更可靠:它在每次输入(包括粘贴、删除、IME 输入)后都触发,且不依赖按键释放。匹配逻辑必须对大小写不敏感,否则 “Apple” 永远匹配不上 “apple”。
- 务必调用
.toLowerCase()统一转换搜索值和列表项文本 - 避免用
==或===做全文等值判断,应使用.includes()或.indexOf() !== -1 - 空字符串时建议显示全部列表项,而不是隐藏所有 —— 否则用户清空输入框后看不到内容
- 不要在循环中反复调用
document.getElementById()或querySelectorAll(),提前缓存 DOM 节点
关键词高亮要用 innerHTML + 正则,不能只改 textContent
仅修改 textContent 无法加样式;想让 “搜索词” 变红或加背景,必须操作 innerHTML 并插入带样式的 span。但直接用 replace() 容易被特殊字符破坏,比如用户搜 [abc],正则会报错 Invalid regular expression。
- 对搜索词做简单转义:
searchText.replace(/[.*+?^${}()|[]\]/g, '\$&') - 构造全局、忽略大小写的正则:
new RegExp(escaped, 'gi') - 替换时用函数捕获匹配项,确保原大小写保留:
text.replace(regex, match => `${match}`) - 高亮前先恢复原始文本(比如存到
data-original),避免重复包裹导致嵌套span
防抖不是可选,是防止卡顿的必要手段
用户快速连打 “react” 时,若每键都执行一次 DOM 遍历 + 正则替换,浏览器会明显卡顿,尤其列表超过 50 项。原生 JS 没有内置防抖,必须手动实现。
- 用
setTimeout+clearTimeout控制延迟执行,推荐 200–300ms - 把防抖逻辑封装成独立函数,避免在事件回调里重复写
let timer - 注意:防抖后要处理“输入结束但未触发”的边界,比如失焦(
blur)时立即执行一次 - 别用 Lodash 的
debounce—— 就为一个搜索框引入整包,体积和维护成本都不值
匹配失败时显示“无结果”需手动控制 DOM
隐藏所有 li 后,用户不知道是没数据还是搜错了。纯 CSS 无法根据兄弟元素数量自动显示提示,必须用 JS 判断并插入/移除提示节点。
- 在筛选循环结束后,检查是否至少有一个
li的style.display !== 'none' - 提示节点建议用
insertAdjacentHTML('beforeend', ...)插入到列表末尾,而非innerHTML += - 提示文字不要写死,比如
无匹配结果,而应动态拼接:未找到包含 “${filter}” 的项目 - 如果列表本身为空(初始无
li),提示逻辑要区分 “数据为空” 和 “搜索无结果”,二者语义不同
真实项目里最容易被跳过的,是高亮后焦点管理与键盘导航支持 —— 用户按上下键切选项、回车确认,这些不是锦上添花,而是可访问性的硬性要求。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











