A07 表单与输入控件
摘要:表单是页面上唯一把数据送回服务器的结构。一个可用表单要同时满足四件事:控件与标签正确关联、提交地址与方法明确、必填与格式由浏览器先拦一次、提交后能看到结果。本文按「控件选择 → 标签关联 → 校验属性 → 提交流程」四步搭建一个报名表单,并给出不写后端时的验证办法。
关键词:表单,输入控件,标签关联,前端校验,提交
所属:frontend/html / A-入门 | 上一篇:A06-列表与表格 | 下一篇:A08-语义化页面骨架
1 引言
表单的核心不是「长得像表单」,而是控件有名字、有标签、有校验、有去处。四项缺任何一项,表单都会表现为「能填但提交失败」或「读屏软件只念出一串输入框」。
本文给出一个报名表单的完整写法,覆盖八类控件与四种校验。范围见表 1-1。
| 项 | 本文覆盖 | 本文不覆盖 |
|---|---|---|
| 控件 | text、email、password、number、date、radio、checkbox、file、select、textarea | 富文本编辑器、日期选择器定制 |
| 关联 | label for、fieldset/legend |
ARIA 高级属性(C 阶段) |
| 校验 | required、type、min/max、pattern | 后端校验与错误提示聚合 |
| 提交 | action、method、enctype |
接口实现与跨域处理 |
2 预备知识
| 项 | 要求 | 核对方式 |
|---|---|---|
| 环境 | A02 的本地服务器 | 能访问 localhost |
| 浏览器 | Chrome 130+ / Edge 130+ | 地址栏 about:version 查看 |
| 文件 | html-practice/form.html |
后缀 .html,UTF-8 |
| 前置 | A06 | 能写 ul 与 table |
| 可选 | 一段能接收 POST 的服务或表单测试服务 | 无后端时按 4 节步骤 4 验证 |
3 原理与实现
3.1 提交是一次完整的往返
表单提交不是页面内的动作,而是浏览器向服务器发一次请求,再按响应跳转,如图 3-1 所示。
sequenceDiagram
autonumber
participant U as 用户
participant B as 浏览器
participant S as 服务器
U->>B: 填写并点击提交
B->>B: 按 required/type 做一次校验
alt 校验未通过
B-->>U: 聚焦首个错误控件并提示
else 校验通过
B->>S: 按 method 与 enctype 发送数据
S-->>B: 返回结果页或重定向
B-->>U: 显示结果
end
图 3-1 表单提交的往返过程
图上可见:浏览器只做粗校验,格式合法但业务不合法的数据仍会到达服务器,服务端校验不可省略。
3.2 完整表单
<!-- 运行环境:Chrome 130+;body 内内容 -->
<form action="/signup" method="post" enctype="multipart/form-data">
<fieldset>
<legend>报名信息</legend>
<p>
<label for="name">姓名</label>
<input id="name" name="name" type="text" required autocomplete="name" />
</p>
<p>
<label for="email">邮箱</label>
<input id="email" name="email" type="email" required autocomplete="email" />
</p>
<p>
<label for="age">年龄</label>
<input id="age" name="age" type="number" min="16" max="99" step="1" />
</p>
<p>
<label for="date">参加日期</label>
<input id="date" name="date" type="date" required />
</p>
<fieldset>
<legend>方向</legend>
<label><input type="radio" name="track" value="frontend" required /> 前端</label>
<label><input type="radio" name="track" value="backend" /> 后端</label>
</fieldset>
<p>
<label for="bio">自我介绍</label>
<textarea id="bio" name="bio" rows="4" maxlength="200"></textarea>
</p>
<p>
<label for="resume">简历文件</label>
<input id="resume" name="resume" type="file" accept=".pdf,.docx" />
</p>
<p>
<label for="source">获知渠道</label>
<select id="source" name="source">
<option value="">请选择</option>
<option value="search">搜索引擎</option>
<option value="friend">朋友推荐</option>
</select>
</p>
<p>
<label><input type="checkbox" name="agree" value="yes" required /> 已阅读并同意须知</label>
</p>
<button type="submit">提交报名</button>
<button type="reset">重置</button>
</fieldset>
</form>
控件与属性的作用见表 3-1。
| 控件 / 属性 | 作用 | 常见误用 |
|---|---|---|
form action |
提交地址 | 留空导致提交到当前页 |
form method |
get 或 post |
上传文件仍用 get |
enctype |
有文件时必须 multipart/form-data |
上传文件用默认编码,后端收不到 |
label for |
与控件 id 绑定 |
只写文字不绑定,点击文字无反应 |
input name |
提交时的字段名 | 漏写 name,数据不随表单发送 |
type="email" |
邮箱格式校验与移动端键盘 | 全部用 type="text" |
required |
必填校验 | 用星号文案代替校验 |
min/max/step |
数值范围与步长 | 只在前端文案提示 |
pattern |
正则校验 | 正则过严导致正常输入被拒 |
fieldset/legend |
控件分组与组标题 | 单选组不加 legend,读屏无法说明用途 |
button type="submit" |
明确提交按钮 | 省略 type,某些场景默认即为 submit |
规则四条:每个控件必须有 id 与 name,且有对应 label;同一组单选的 name 必须相同、value 不同;含文件上传时必须 method="post" 且 enctype="multipart/form-data";按钮显式声明 type。
4 验证与讨论
- 保存文件,浏览器打开
form.html,确认控件全部渲染。 - 留空姓名直接提交,观察浏览器拦截并聚焦到姓名输入框。
- 填写非法邮箱(如
a@),观察邮箱格式提示。 - 把
action改为https://httpbin.org/post,提交后查看返回的 JSON,确认字段名与值都随请求发送。 - 对照表 4-1 逐项检查。
| 检查项 | 预期结果 | 不通过时先看 |
|---|---|---|
| 点击标签文字 | 对应输入框获得焦点 | label for 与 id 是否一致 |
| 必填校验 | 留空提交被拦下,提示为浏览器原生样式 | required 是否写在控件上 |
| 邮箱校验 | 输入 a@ 时提示格式错误 |
type="email" |
| 单选取值 | 只能选中一个 | 组内 name 是否相同 |
| 文件上传 | 返回数据中包含文件字段 | enctype 与 method |
| 提交结果 | 返回 JSON 中字段名与 name 一致 |
漏写 name 的控件 |
讨论与局限。 浏览器原生校验的提示文案与样式由浏览器决定,无法用 HTML 改写,统一视觉需要 CSS 与 JavaScript。另外 required 只拦空值,不拦格式;pattern 在部分移动端输入法下行为不一致,正式项目仍以服务端校验为准。
5 常见问题
| 现象 | 原因 | 处理 |
|---|---|---|
| 提交后地址栏出现一长串参数 | method 为默认的 get |
需要提交数据时改 post |
| 文件字段在服务端为空 | 缺少 enctype="multipart/form-data" |
补 enctype,并确认 method="post" |
| 点击标签文字无反应 | label 未绑定 for,或 id 拼错 |
用 for + id 一一对应 |
| 单选能选中多个 | 组内 name 写成了不同值 |
同组统一 name,value 区分 |
| 提交按钮无反应 | 按钮在 form 外部 |
移入 form,或加 form 属性关联 |
| 数字输入框允许小数 | step 默认为 1 但未显式声明 |
明确 step="1" |
6 结论
| 序号 | 结论 | 依据 |
|---|---|---|
| 1 | 表单是浏览器到服务器的往返,不是页面内动作 | 图 3-1 |
| 2 | 控件三件套:id、name、label |
表 3-1 |
| 3 | 文件上传必须 post + multipart |
表 3-1 |
| 4 | 浏览器校验只能拦住空值与格式 | 4 节步骤 4、讨论 |
- 上一篇:A06-列表与表格
- 下一篇:A08-语义化页面骨架
- 返回:A00-总结 | 科目 README
参考文献
[1] MDN Web Docs · 表单与按钮,https://developer.mozilla.org/zh-CN/docs/Learn/Forms(访问于 2026-10-29)
[2] MDN Web Docs · 客户端表单校验,https://developer.mozilla.org/zh-CN/docs/Learn/Forms/Form_validation(访问于 2026-10-29)

评论 0
还没有评论,快来抢沙发吧~