一、表单是什么?为什么要学?
只要你上过网,你就用过表单——登录要填账号密码、注册要填信息、搜索要输入关键词、下单要填收货地址……所有这些,背后都是 HTML 表单在干活。
一句话定义:表单(Form)就是网页上用来「收集用户输入信息」,并把信息「提交给服务器处理」的那块区域。
一个典型的登录流程长这样:
用户在表单输入用户名 & 密码
↓ 点击登录
表单将数据提交到服务器(action 指定的地址)
↓
服务器收到数据 → 查数据库 → 做业务判断
↓
服务器把结果响应回浏览器
↓
登录成功跳转 / 失败显示提示
表单就是浏览器与服务器之间的桥梁。
二、表单基础:<form>标签
所有表单项必须放在 <form>...</form>里才有"提交"的概念。最基础的骨架:
<form action="服务器处理地址" method="提交方式" name="表单名称">
<!-- 表单项放这里 -->
</form>
form 的核心属性
| 属性 | 作用 | 说明 |
|---|---|---|
| action | 指定表单提交到的服务器 URL | 比如 action="/api/login"或 action=“login.php” |
| method | 指定提交方式 | 只有 GET或 POST,不写默认是 GET |
| name | 给表单起名 | 一个页面可有多个表单,用 name 区分(现代开发中用得少了,但学了要知道) |
| enctype | 编码方式 | 上传文件时必须设为 multipart/form-data |
| target | 响应结果显示在哪 | _self(当前页,默认)/ _blank(新窗口)等 |
⚠️ 关键规则:表单项想被提交到服务器,必须有 name属性! 没有 name 的表单项,提交时会被忽略。
三、GET 与 POST 的区别(重点!附常见误区纠正)
method="get"或 method=“post”,决定了表单数据怎么送到服务器。
本质区别一览
| 对比维度 | GET | POST |
|---|---|---|
| 数据放哪 | 拼在 URL 后面(?key=value&…) | 放在 HTTP 请求体(Request Body)中 |
| 地址栏可见? | ✅ 参数直接暴露在 URL 里 | ❌ URL 中看不到参数内容 |
| 能否收藏/分享 | ✅ URL 自带参数,可收藏 | ❌ 无法仅通过 URL 复现 |
| 长度限制 | 受限于浏览器/服务器对 URL 长度的限制(非 HTTP 协议本身限制) | 理论上无限制,但实际受服务器配置约束(如 Nginx/Tomcat 会设上限) |
| 典型场景 | 搜索、筛选等查询操作 | 登录、注册、提交订单等有副作用的操作 |
看一眼就懂的直观对比
// GET 方式提交后,地址栏会变成这样:
https://example.com/login?username=admin&password=123456 ← 密码直接暴露!❌
// POST 方式提交后,地址栏干干净净:
https://example.com/login ← 数据在请求体里,URL 看不见 ✅
🔥 三个常见误区的纠正
| 误区 | 真相 |
|---|---|
| “GET 限 2KB” | HTTP 协议本身不对 URL 长度设限。限制来自浏览器和服务器(IE 约 2083 字符,多数现代浏览器更长)。但确实不该用 GET 传大量或敏感数据,不是因为"协议规定 2KB",而是 URL 有现实限制 + 安全问题 |
| “POST 比 GET 安全,所以全用 POST” | POST 只是不把参数显示在 URL,但抓包照样能看到请求体。真正的安全靠 HTTPS 加密,不是靠换方法。查询场景用 GET 更符合语义、可缓存 |
| “POST 无限大” | 理论上 HTTP 不限制,但你的服务器(Nginx/Tomcat/PHP…)一定会设上限,超大文件要走分片上传 |
👉 实际开发怎么选?
- 搜索框、筛选条件 → method=“get”(参数在 URL 里,方便分享和收藏)
- 登录、注册、修改密码、提交订单 → method=“post”(敏感数据别放 URL)
四、表单项详解 —— 一个一个来
表单项是 <form>里面放的各种输入控件。绝大多数都是 <input>变体(靠 type区分),再加上 <select>、<textarea>、<button>这几个"独立门派"。
4.1 文本框 — type=“text”
最最常用的单行输入框:
<form>
用户名:<input type="text" name="username" placeholder="请输入用户名">
</form>
| 属性 | 作用 |
|---|---|
| name | 提交时的键名(必须有) |
| value | 默认值 |
| placeholder | 浅色提示文字,用户一点击就消失 |
| maxlength | 最多允许输入多少字符 |
4.2 密码框 — type=“password”
跟文本框一模一样,区别是输入内容会被遮挡(显示为 •或 *):
密码:<input type="password" name="pwd" placeholder="请输入密码">
4.3 提交按钮 — type=“submit”
点击后,表单数据会被打包提交到 action指定的地址:
<input type="submit" value="登录">
💡 试一试:写好一个 GET 表单,填完点提交,盯着地址栏看参数变化——秒懂 GET 是怎么拼 URL 的。
4.4 单选按钮 — type=“radio”
一组互斥的选项,同一时刻只能选一个:
性别:
<input type="radio" name="sex" id="male" value="male">
<label for="male">男</label>
<input type="radio" name="sex" id="female" value="female">
<label for="female">女</label>
两个铁律:
- 同一组单选按钮的 name必须相同(靠 name 分组)
- 必须写 value(提交时传的是 value,不是显示的文字)
- 配合
<label>+ for/id 使用,点文字也能选中(见下文详讲)
默认选中加 checked:
<input type="radio" name="sex" id="male" value="male" checked>
4.5 复选框 — type=“checkbox”
可以多选,勾选了哪些就提交哪些的 value:
爱好:
<input type="checkbox" name="hobby" id="smoke" value="smoking">
<label for="smoke">抽烟</label>
<input type="checkbox" name="hobby" id="drink" value="drink">
<label for="drink">喝酒</label>
<input type="checkbox" name="hobby" id="perm" value="perm">
<label for="perm">烫头</label>
⚠️ 同一组复选框的 name也要一样(如都叫 hobby),后端收到的是 hobby=smoking&hobby=drink这种同名多值的形式。
4.6 重置按钮 — type=“reset”
一键清空所有表单项回到初始值:
<input type="reset" value="重置">
😅 谨慎用!用户辛辛苦苦填了一半,手滑点了重置……那种感觉你懂的。很多团队直接禁用重置。
4.7 普通按钮 — type=“button”
没有默认行为,就是个按钮壳子,等着你用 JS 绑定功能:
<input type="button" value="点我弹个窗" onclick="alert('Hello!')">
现代写法更推荐用 <button type="button">(见 4.11)。
4.8 下拉列表 — <select>+ <option>
节省空间的四两拨千斤方案:
城市:
<select name="city">
<option value="0">-- 请选择 --</option>
<option value="bj">北京</option>
<option value="sh">上海</option>
<option value="gz">广州</option>
</select>
| 要点 | 说明 |
|---|---|
<select>的 name | 提交时的键名 |
<option>的 value | 选中时提交的值(不写 value 则提交标签里的文字) |
| selected | 加在某 <option>上,让它默认选中 |
<option value="bj" selected>北京</option> <!-- 默认选中北京 -->
想分组?用 <optgroup>:
<select name="city">
<optgroup label="华北">
<option value="bj">北京</option>
<option value="tj">天津</option>
</optgroup>
<optgroup label="华东">
<option value="sh">上海</option>
<option value="hz">杭州</option>
</optgroup>
</select>
多选模式(multiple,Ctrl/Cmd + 点击多选):
<select name="hobby" multiple size="4">
<option value="1">篮球</option>
<option value="2">足球</option>
<option value="3">羽毛球</option>
</select>
4.9 多行文本框 — <textarea>
不是 <input>!它是一个独立的双标签元素,用于多行文本(留言、简介、评论等):
<textarea name="intro" rows="5" cols="40" placeholder="介绍一下自己..."></textarea>
| 属性 | 作用 |
|---|---|
| rows | 可见行数(高度) |
| cols | 可见列数(宽度) |
| maxlength | 最大字符数 |
📌 默认值直接写在开闭标签之间(不是 value 属性):
<textarea name="msg">这里是默认内容</textarea>
4.10 隐藏域 — type=“hidden”
页面上看不见,但提交表单时会带上这个值。常用于:偷偷传一个用户 ID、CSRF token、操作类型等:
<input type="hidden" name="userId" value="10086">
<input type="hidden" name="action" value="delete">
4.11 <button>标签 —— 比 <input type="submit">更好用的按钮
<button>是现代 HTML 推荐的按钮写法,因为它可以放图标、斜体、图片等富内容,而 <input type="submit">只能纯文字:
<button type="submit">🚀 提交登录</button>
<button type="reset">重置</button>
<button type="button">啥也不做(等你绑JS)</button>
| type值 | 行为 |
|---|---|
| submit(默认!) | 提交表单 |
| reset | 重置表单 |
| button | 无默认行为,纯容器 |
⚠️ 没有显式写 type的
<button>默认是 submit——如果把它放进<form>里却只想当普通按钮用,记得写 type=“button”,否则一点击就提交了!
4.12 <label>—— 提升用户体验的关键(重点!)
痛点:单选/复选框只有点那个小圆圈或小方块才能选中,点旁边的文字没反应——太难瞄准了。
<label>的解决方案:把文字和输入框关联起来,点文字 = 点输入框:
方式一:显式关联(for↔ id)👉 推荐
<input type="radio" name="sex" id="male" value="male">
<label for="male">男</label>
<input type="radio" name="sex" id="female" value="female">
<label for="female">女</label>
label的 for值 = 对应表单元素的 id值
方式二:隐式关联(嵌套)
<label>
<input type="checkbox" name="agree" value="yes"> 我已阅读并同意用户协议
</label>
✅ 好处不仅是"点文字能选中"——屏幕阅读器等辅助技术也靠 label 读出字段含义,这是无障碍访问(Accessibility)的基本要求。
五、表单项常用属性速查
| 属性 | 能用在哪 | 作用 |
|---|---|---|
| name | 几乎所有表单项 | 提交时的键名(没有 name = 不提交) |
| value | input / hidden 等 | 默认值 / 提交值 |
| placeholder | text / password / textarea 等 | 提示文字(输入后消失,不能替代 label!) |
| autofocus | 可聚焦的控件 | 页面加载后自动聚焦到这里(整个文档只能有一个) |
| checked | radio / checkbox | 默认选中 |
| selected | option | 下拉列表默认选中 |
| readonly | text / password / textarea 等 | 只读(能看、能选、能复制,不能改,值仍会提交) |
| disabled | 几乎所有 | 禁用(灰掉、不可操作,值不会提交) |
| required | text / password / radio / checkbox / select / textarea 等 | 必填约束(HTML5 原生校验) |
| minlength/ maxlength | text / password / textarea | 最少 / 最多字符数 |
| min/ max/ step | number / date / range 等 | 数值或日期的范围 |
| pattern | text / tel / email 等 | 正则表达式校验(如 pattern="[0-9]{11}"限定11位数字) |
readonly vs disabled对照
| 用户能改? | 能聚焦? | 值会提交? | 外观 | |
|---|---|---|---|---|
| readonly | ❌ | ✅ | ✅ | 正常 |
| disabled | ❌ | ❌ | ❌ | 灰色 |
六、一个完整可运行的登录表单示例
把下面代码保存成 .html文件,浏览器打开就能跑:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>登录表单示例</title>
<style>
body {
font-family: system-ui, sans-serif;
background: #f5f5f5;
display: flex;
justify-content: center;
padding-top: 60px;
}
form {
background: #fff;
padding: 32px 28px;
border-radius: 10px;
box-shadow: 0 4px 24px rgba(0,0,0,.1);
width: 340px;
}
h2 { margin-top: 0; text-align: center; }
label {
display: block;
margin-top: 14px;
font-size: 14px;
color: #333;
}
input[type="text"],
input[type="password"] {
width: 100%;
padding: 8px 10px;
margin-top: 4px;
border: 1px solid #ccc;
border-radius: 6px;
font-size: 14px;
box-sizing: border-box;
}
input:focus { outline: none; border-color: #4a90d9; box-shadow: 0 0 0 3px rgba(74,144,217,.2); }
button {
margin-top: 20px;
width: 100%;
padding: 10px;
border: none;
border-radius: 6px;
background: #4a90d9;
color: #fff;
font-size: 15px;
cursor: pointer;
}
button:hover { background: #357abd; }
.tip { font-size: 12px; color: #999; margin-top: 2px; }
</style>
</head>
<body>
<form action="/api/login" method="post">
<h2>🔐 用户登录</h2>
<label for="username">用户名</label>
<input type="text" id="username" name="username" placeholder="手机号/邮箱" required autofocus>
<label for="pwd">密码</label>
<input type="password" id="pwd" name="password" placeholder="请输入密码" required minlength="6">
<span class="tip">至少 6 位字符</span>
<label style="margin-top:12px">
<input type="checkbox" name="remember" value="1"> 记住我
</label>
<button type="submit">登 录</button>
</form>
</body>
</html>
点提交后会跳到 /api/login(因为没有真实后端,浏览器会报 404——但打开 DevTools → Network 面板,你能清楚看到 POST 数据和请求体内容,这就是表单运作的真实样貌)。
七、避坑 Checklist ✅
| 坑 | 正确做法 |
|---|---|
| 表单项没提交出去 | 先检查有没有写 name属性 |
| 密码明文出现在地址栏 | 把 method改成 post |
点了 <button>莫名其妙提交了 | 补上 type=“button”,因为默认是 submit |
| 点单选/复选的文字选不中 | 用 <label for="id">关联起来 |
| 用 placeholder代替了 label | placeholder 只是提示,屏幕阅读器读不到它——该写 <label>还是要写 |
| 重置按钮惹恼用户 | 要么不用,要么加确认:οnsubmit=“return confirm(‘确定重置?’)” |
| 以为前端校验就够了 | required/ pattern只是 UX 友好层,后端必须二次校验(用户能关 JS、能直接发 HTTP 请求) |
八、延伸:HTML5 还给表单加了哪些"隐藏福利"?
你现在已经掌握了表单的全部核心。顺带一提,HTML5 默默送了你一堆免费能力,不需要 JS 就能用:
| 新输入类型 | 效果 | 示例 |
|---|---|---|
| type=“email” | 自带邮箱格式校验 | <input type="email" required> |
| type=“url” | 自带 URL 格式校验 | <input type="url"> |
| type=“number” | 只能输数字 + 上下箭头 | <input type="number" min="1" max="100"> |
| type=“date” | 日期选择器 | <input type="date"> |
| type=“range” | 滑块 | <input type="range" min="0" max="100"> |
| type=“file” | 文件选择(加 multiple可多选) | <input type="file" accept="image/*"> |
加上 required、pattern、:valid/ :invalidCSS 伪类,原生表单的体验已经相当不错了——很多场景甚至不需要写一行 JS。
总结一张脑图
<form action="" method="">
├── 文本输入 → <input type="text">
├── 密码输入 → <input type="password">
├── 单选 → <input type="radio"> (同组 name 相同 + value 必写)
├── 多选 → <input type="checkbox">
├── 下拉 → <select> + <option> (value 必写)
├── 多行文本 → <textarea>
├── 隐藏域 → <input type="hidden">
├── 提交按钮 → <button type="submit"> 或 <input type="submit">
├── 重置按钮 → <input type="reset"> (慎用)
├── 普通按钮 → <button type="button"> + JS
└── 无障碍桥梁 → <label for="id"> (点文字 = 聚焦控件)
表单表面简单,深处连着网络通信(HTTP)→ 服务器处理 → 数据库 → 安全。把这些标签和属性吃透,你就握住了前后端交互的第一把钥匙。
读者互动:
- 如果你觉得文章有待改进,请在评论区留言,我会认真考虑每一条建议。
- 如果觉得文章有帮助,欢迎点赞鼓励。
- 想与我共同进步,欢迎关注我。
💬 感谢各位读者的支持与关注!期待与大家一起在前端开发的道路上共同进步!🎉

999

被折叠的 条评论
为什么被折叠?



