单选题组必须使用相同name且每个radio带value,否则后端无法识别为同一题;textarea和range需同form且独立name;须用fieldset+legend语义化包裹题目;提交需阻止默认行为并校验前后端。

单选题组必须用相同 name,且每个 input 带 value
浏览器只提交带 value 的选项;name 不一致,后端就收不到“一道题”的完整语义。比如第2题四个选项写成 name="q2_a"、name="q2_b",后端拿到的是四个独立字段,而不是一个逻辑题。
- 正确写法:
<input type="radio" name="q2" value="a"><label for="q2-a">A. 正确</label>(注意for和id严格匹配) - 漏写
value→ 提交值为空字符串,后端无法判断用户是否作答 - 初始不设
checked也没关系,但提交前必须至少选一个,否则required会聚焦到第一个 radio 上 - 别用
type="radio"却把所有value都写成"radio"——这是常见复制粘贴错误
textarea 和 input[type="range"] 必须共用一个 form,且各自有独立 name
评分和文字评价是两类数据,不能混在同一个 name 下,也不能分拆到两个 form 标签里——否则只有一半数据能提交成功。
-
<input type="range" name="score" min="1" max="5" value="3">比number更稳妥:避免用户输 0 或 6,移动端拖动也更自然 -
<textarea name="feedback"></textarea>必须带name,否则内容根本不会出现在 POST 请求体中 - 如果允许只打分不写评语,就别给
textarea加required;加了就得填,否则表单拦不住提交 - name 值禁用中文、空格、点号(如
name="用户反馈"或name="review.text"),PHP/Node 默认不解析,字段直接丢失
提交时页面刷新或跳转,说明没拦截原生行为
原生 form 提交默认触发页面跳转,你看到的“没反应”“数据丢了”,大概率是因为没阻止它,也没手动发请求。
- 最简方案:
<form onsubmit="submitAnswers(); return false"></form>——return false是关键,否则事件继续冒泡导致跳转 - 更推荐用
event.preventDefault()+FormData+fetch:能精确控制 loading 状态、错误提示、响应处理 - 调试时打开开发者工具 → Network → Payload,确认发送的键名(如
score、feedback、q1)和值是否符合预期 - 别写
onsubmit="return false"就完事——那按钮点了没任何动作,用户以为坏了
用 fieldset + legend 包裹每道题,不是可选项
这不是为了好看,而是语义化和可访问性的硬性要求:屏幕阅读器靠 legend 识别题组边界,自动化测试工具靠它定位题目范围,键盘 Tab 导航也依赖这个结构。
-
<fieldset> <legend>第4题</legend>...</fieldset>是最小合规单元 - 不用
div模拟选项——哪怕样式再灵活,也会丢掉表单序列化、键盘操作(空格/回车切换)、无障碍支持 - 多选题(
checkbox)同样适用fieldset,但要注意:它的required无法强制“至少选一个”,必须用 JS 检查document.querySelectorAll('input[name="q5"]:checked').length - 别省略
for/id关联——点击文字不生效,移动端点击热区太小,对触控极不友好
range 输入的二次校验。前端限制 min="1" max="5" 只是体验层防护,用户仍可通过 DevTools 修改 DOM 或直接发请求绕过。真正可靠的校验必须落在服务端。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











