搜索历史这种功能,推荐用 `localStorage` —— 用户关了浏览器下次回来还想看到之前搜过的词,`sessionStorage` 一关就清空,不适合“历史”这个需求。不过有几个点得注意:容量限制(通常 5–10MB,存几十条短文本完全够用)、同源页面共享(按域名隔离)、JSON 解析时记得
搜索历史这种功能,推荐用 `localStorage` —— 用户关了浏览器下次回来还想看到之前搜过的词,`sessionStorage` 一关就清空,不适合“历史”这个需求。不过有几个点得注意:容量限制(通常 5–10MB,存几十条短文本完全够用)、同源页面共享(按域名隔离)、JSON 解析时记得做容错处理、还要限制条数和去重。

先说存储选型。`localStorage` 和 `sessionStorage` 的区别,关键在于生命周期。用户关闭浏览器后还想保留搜索词,就得用 `localStorage`。`sessionStorage` 关掉标签页就没了,连刷新都不一定靠得住(有些浏览器刷新后依然活着,但总体不可控)。容量方面不用担心,5–10MB 的额度存几十条短文本绰绰有余。而且它是按域名隔离的,同源下的不同页面都能读到同一份数据。
长期稳定更新的攒劲资源: >>>点此立即查看<<<
实际操作时,写入用 localStorage.setItem('searchHistory', JSON.stringify(historyArray)),读取前一定加个 try...catch —— 万一用户手动修改了 localStorage 里的值导致 JSON 解析失败,整个功能就会崩溃。还要限制历史条数,比如最多存 10 条。插入新词时先 historyArray.unshift(newTerm),再用 historyArray.splice(10) 截断,简单高效。
重点不在于等待搜索结果返回后再存储,而在于捕捉触发搜索动作的时刻。哪怕搜索失败了,也得把这次输入的词记下来,否则用户历史里会莫名其妙缺了记录。常见错误是只在 fetch 成功的回调里存,网络一断就漏了。推荐做法:监听表单的 submit 事件或按钮的 click 事件,处理函数里第一时间提取 inputElement.value.trim(),非空就调用保存逻辑——不依赖任何异步结果。还要避免重复存储完全相同的词:简单的做法是判断 historyArray[0] !== newTerm,或者用 Array.from(new Set([...historyArray, newTerm])).slice(-10) 保证去重且保留原始顺序。
千万别用 innerHTML += ... 拼接,万一历史词里藏了个 ,XSS 漏洞就开了口子。用 document.createElement 创建 span,设 textContent 而不是 innerHTML,安全第一。遍历 historyArray,为每个词创建元素,绑定 click 事件:点击后把词填回输入框并触发提交(比如 inputElement.value = term; form.submit())。加一个 CSS 类名(如 search-history-item)方便样式统一,别用行内 style。如果数组为空,显示“暂无搜索历史”,别留白也别报错。
几个典型坑:大小写或空格没处理——用户搜 "react" 和 "React " 被当成两条不同的记录;跨页面路径问题:虽然 `localStorage` 同源共享,但如果有多个页面用了不同的 JS 版本(比如 Service Worker 缓存了旧脚本),可能读到过期数据。排查时打开开发者工具 → Application → Local Storage,直接看 searchHistory 的值对不对。还要检查有没有代码在某个地方调了 localStorage.clear(),特别是某些 UI 框架的“重置状态”逻辑。另外注意 Safari 隐私模式下 `localStorage` 会抛 QuotaExceededError,要兜底 try/catch 并降级为内存存储(刷新后消失)。最后别忘了:修改完历史数组后要重新渲染 DOM,否则 Vue/React 的响应式机制可能绕过你——纯 HTML 场景倒没这个问题。
真实项目里,搜索历史看似简单,边界情况全集中在“存储时机”和“DOM 同步节奏”上。不是写完就能跑通的,得在输入、提交、刷新、多标签页切换这几种场景下都验证一遍。
侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述