搜索框必须用 method="get" 的 form 包裹 name="q" 的 input[type="search"],否则回车和软键盘搜索无效;需用 submit 事件拦截并 preventdefault,结果页用 main+ol/ul+li 结构,高亮要防 xss 并匹配单词边界。

搜索框必须用 form 包裹 input[type="search"]
不包 form 的搜索框,按回车不会提交,移动端软键盘的「搜索」按钮也无效。浏览器对 input[type="search"] 有原生支持:自动添加清除按钮、语音图标、历史下拉菜单——这些能力全靠语义触发。
常见错误是只写 input,或用 div 模拟表单。这会导致服务端收不到 q=xxx 参数,屏幕阅读器也无法识别为搜索控件。
-
form的method必须设为"GET",让关键词出现在 URL 中,方便分享和刷新复现 -
input必须有name="q"(行业惯例),否则提交时参数不会被序列化 - 不要加
autocomplete="off",除非是敏感场景(如后台管理搜密码);禁用后用户无法复用历史词
拦截提交要用 submit 事件,不是 keyup 或 click
监听 input 的 change 或 keyup 容易误触发:比如用户按方向键、删空格、切换输入法时都算“变化”,但并不想立刻搜索。
form 的 submit 事件才是真正的确认信号,它覆盖所有路径:回车、软键盘搜索键、点击按钮、甚至快捷键(如 Ctrl+Enter)。
- 必须调用
event.preventDefault(),否则页面会跳转或刷新 - 之后可走 AJAX、
history.pushState()跳路由,或本地过滤——逻辑自己定,但入口统一 - 别给按钮单独绑
onclick:按钮可能被隐藏、替换成图标,或由快捷键触发
搜索结果页结构必须用 main + ol/ul + li
把结果堆在 div 里看着自由,实则埋坑:搜索引擎抓不到标题层级,屏幕阅读器读不出这是“结果列表”,键盘用户 tab 导航会跳得乱。
标准结构是用 main 包裹整个结果区,每条结果用 li,标题用 h3,摘要用 p,链接用 a 标签包裹整条内容——这样语义清晰、SEO 友好、焦点流自然。
-
ul#result-list要显式重置样式:list-style: none; margin: 0; padding: 0;,避免各浏览器默认缩进不一致 - 每条
li用border-bottom分隔比margin-bottom更稳,最后一项用:last-child { border-bottom: none; } - 空状态不能留白:要显示提示文字,并保持搜索框可聚焦(
input.focus()),否则用户得手动点回去
关键词高亮必须防 XSS,且匹配要带单词边界
纯 HTML 做不了动态高亮,必须用 JS 处理字符串并插入 <mark></mark>。但直接 innerHTML = str.replace(...) 极其危险——如果搜索词含 <script></script>,就执行了脚本。
更隐蔽的问题是匹配太宽:用户搜 js,你不该把 javascript 里的 js 也高亮,那会误导。
- 先对关键词做 HTML 转义,再构造正则:
keyword.replace(/[.*+?^${}()|[]\]/g, '\$&') - 用
匹配单词边界:new RegExp(`\b(${escaped})\b`, 'gi') - 安全插入 DOM:用
document.createTextNode()创建纯文本节点,再拼接<mark></mark>片段,别依赖innerHTML直接拼接
最常被忽略的是:高亮后没同步更新 URL 的 search 参数,用户刷新页面就丢失关键词;还有移动端 Safari 对 input[type="search"] 的 search 事件支持更稳定,得额外监听。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











