填空题组件可用原生HTML+JS实现,需确保结构语义化、数据可映射、回显不丢值,避开DOM重复ID、正则误匹配、空格/大小写校验失效三类高频坑。

填空题组件不用框架也能做,关键在结构语义化、数据可映射、回显不丢值——原生 HTML + JS 就够用,但必须避开 DOM 重复 ID、正则误匹配、空格/大小写校验失效这三类高频坑。
怎么用 {n} 占位符动态生成填空输入框
用户配置题干时用 {1}、{2} 表示填空位置,JS 需用正则提取并替换成 <input>,但注意:
- 正则必须用
/\{(\d+)\}/g(带全局 flag 和捕获组),不能只写/\{.*?\}/,否则多层嵌套或连续占位会错位 - 替换时每个
input的name设为blank-1、blank-2,避免 name 重复导致表单提交只取最后一个值 - 别给 input 加固定
id,改用data-index="1"存位置,回显和校验都靠它查数组 - 原始题干里如果有字面量
{1}(比如讲正则的题目),需提前转义,例如写成\{1\},并在匹配前先还原
填空答案怎么比对才不容易判错
用户输入和标准答案直接 === 会因空格、换行、大小写失败,必须统一预处理:
- 用
String(value).trim().toLowerCase().replace(/\s+/g, ' ')标准化两边字符串 - 填空题的
answer字段建议存为数组(如["HTTP", "http", "Http"]),校验时用answers.some(a => unify(a) === unify(input.value)) - 如果题干含多个填空,
dataset.answer可设为 JSON 字符串,如data-answer='["GET", "POST"]',解析后逐项比对 - 不要在 input 上加
required后就以为前端校验完整了——空格输入、全角空格、零宽字符仍能绕过,必须 JS 层二次清洗
怎么让填空组件支持回显且不污染原始 DOM
用户刷新或编辑时要恢复上次填写的内容,但不能靠 innerHTML 替换整个题干(会丢失事件绑定和已输入值):
立即学习“前端免费学习笔记(深入)”;
- 初始化时遍历所有
input[data-index],从保存的数据对象中取data[index]赋值给input.value - 不要用
innerHTML.replace()把答案再塞回去——那会销毁 input 元素,导致焦点丢失、输入历史清空 - 如果题干是富文本(含
<strong>或换行),填空位置要用<span class="blank-placeholder" data-index="1"></span>占位,再用 JS 把 input 插入该位置,而非直接替换文本 - 回显前检查数据长度是否匹配填空数量,少于项数就补空字符串,多于项数就截断,避免
index out of bounds
为什么用 <form> 包裹填空题比单独用 <div> 更稳
不是为了提交到后端,而是借力浏览器原生机制:
-
form.checkValidity()可批量触发所有required填空的验证气泡提示 - 监听
form.submit事件做统一拦截,比给每个 input 绑blur更轻量 - 用
form.dataset.answer存标准答案,比挂全局变量或查 DOM 更解耦 - 如果后续要加「重置」按钮,直接
form.reset()就清空所有填空,不用手动遍历 input
最易被忽略的是:填空位置索引必须从 1 开始且连续。如果题干里写了 {1} 和 {3} 中间漏了 {2},回显数组下标就会错位——要么强制校验配置合法性,要么在校验时用 Map 以 index 为 key 存答案,不依赖数组顺序。



















