用 checkbox 实现错题本开关最稳妥,语义准确、无障碍友好;状态应由服务端预注入并配合幂等 API 同步,避免 localStorage 单点故障与多端不同步。

错题本开关用 checkbox 最稳妥
用户点“加入错题本”本质是做一次布尔标记,不是提交表单也不是跳转页面。checkbox 天然支持 checked/unchecked 状态,语义准确,无障碍友好,且不用额外监听 click 或 preventDefault。
常见错误是用 button + JS 手动维护状态,结果忘了持久化、没同步 UI、或在 SSR 场景下首屏闪动。
实操建议:
- 用
<input type="checkbox" id="add-to-wrongbook">,配合<label for="add-to-wrongbook">加入错题本</label> - 不要用
div模拟开关——无法键盘聚焦、不被屏幕阅读器识别、移动端点透风险高 - 如果需默认勾选(比如题目加载时已存在错题记录),后端直接输出
checked属性,别靠 JS 异步 setAttribute
勾选后数据怎么存到错题本?别只靠前端 localStorage
用户关掉页面再打开,错题不该消失;换设备也该同步。仅用 localStorage.setItem('wrongbook', JSON.stringify(ids)) 看似简单,但实际会踩三个坑:
常见错误现象:A 用户在手机勾了题,PC 端刷新后没显示;B 多个标签页同时操作导致覆盖;C 题目 ID 格式不一致("q1024" vs 1024)存进数组后去重失败。
实操建议:
- 勾选变更时,立即发轻量 POST 到
/api/wrongbook/toggle,传{ question_id: "q1024", action: "add" }或"remove" - 前端本地缓存只作 fallback:网络失败时存
localStorage,恢复后补发;成功响应才更新 UI 和本地副本 - 服务端必须幂等:重复 add 同一题 ID 不报错、不重复插入
HTML 里怎么让“错题标识”视觉可感知又不干扰阅读?
错题本开关不是装饰,用户需要一眼确认当前题是否已在本中。但加 icon、变色、加边框都可能破坏排版节奏,尤其在密集题干列表里。
性能与兼容性影响:用 CSS ::before 插入图标要防字体加载失败;用 background-image 增加 HTTP 请求;用 JS 动态加 class 容易和 SSR 内容不一致。
实操建议:
- 直接在
label里放 SVG 图标,内联写死,无请求、无闪烁:<label><svg viewbox="0 0 16 16"><path d="M13 4v2h-2V4h2m-4 0v2H7V4h2m-4 0v2H3V4h2M5 8v2H3V8h2m4 0v2H7V8h2m4 0v2h-2V8h2m-4 4v2H7v-2h2m4 0v2h-2v-2h2m-4 4v2H7v-2h2m4 0v2h-2v-2h2z"></path></svg> 加入错题本</label> - 用
:checked + label控制图标颜色,不依赖 JS - 禁用状态(如题目已过期不可加入)用
disabled属性,别只靠 opacity 或 pointer-events
服务端返回错题状态时,HTML 怎么避免重复渲染?
用户打开试卷页,要立刻知道哪些题已进错题本。如果等所有题 DOM 渲染完再批量查 API,会出现“先显示空白开关,再突然打钩”的抖动;如果每个题都单独发请求,又触发浏览器并发限制和服务器压力。
容易被忽略的点:服务端模板(如 Django/Jinja)在生成 HTML 时,其实已经能拿到用户错题 ID 集合。硬要推给前端异步查,等于放弃最高效的一次性注入机会。
实操建议:
- 后端在吐 HTML 前,把当前页所有题 ID 对应的错题状态预计算好,注入为全局 JS 变量:
<script>window.__WRONGBOOK_SET__ = new Set(["q1024", "q2048"]);</script> - 前端初始化 checkbox 时,直接读
window.__WRONGBOOK_SET__.has(questionId)设checked,零延迟 - 这个 Set 必须用字符串 key,避免数字 ID 被 JS 自动转成 number 导致
has(1024)查不到"1024"
立即学习“前端免费学习笔记(深入)”;
事情说清了就结束



















