用 fetch 提交表单需阻止默认行为,用 FormData 构造数据并处理文件、cookie、Content-Type;必须检查 response.ok、try/catch response.json();按钮防重复点击并恢复状态;字段级错误要精准定位并提示。

用 fetch 提交表单,别再用 submit 刷新页面了
直接阻止默认提交行为,用 fetch 发送数据是最轻量、兼容性足够(Chrome 42+、Firefox 39+、Safari 10.1+)的方案。关键不是“能不能发”,而是“怎么发才不丢数据、不崩格式、不漏错误”。
常见错误:直接把 form 元素传给 fetch,或手动拼 URLSearchParams 却忽略文件字段;还有没处理 Content-Type 导致后端收不到 name 字段。
- 用
new FormData(formElement)构造数据——它自动适配文本字段和<input type="file"> - 如果后端只认
application/json,得先调Object.fromEntries(new FormData(form))转对象,再JSON.stringify(),但注意:文件字段会丢失(File对象不能被 JSON 序列化) -
fetch默认不带 cookie,登录态会失效,加{ credentials: 'include' }
后端返回 JSON 时,response.json() 必须配合 try/catch
很多人以为 fetch 报错只发生在网络断开时,其实 HTTP 状态码 4xx/5xx 不会触发 catch,而 response.json() 在响应体不是合法 JSON 时(比如 PHP 输出了 warning、Node.js 忘了 res.json())才会真正抛错——这时页面就静默卡住。
- 永远在
response.json()外层包try/catch - 检查
response.ok判断状态码是否在 200–299 范围 - 服务端返回非 JSON(如纯文本
"success")时,改用response.text()
fetch('/api/login', {
method: 'POST',
body: new FormData(form),
credentials: 'include'
})
.then(r => {
if (!r.ok) throw new Error(`HTTP ${r.status}`);
return r.json();
})
.catch(err => {
console.error('提交失败:', err.message);
alert('网络错误或服务器异常');
});
按钮防重复点击和加载态反馈不能只靠 CSS 类
用户狂点提交按钮是常态,尤其移动端。光加 disabled 属性不够——如果请求因网络延迟迟迟未返回,用户刷新页面后按钮仍是禁用态;更糟的是,若 JS 执行出错,disabled 可能永远不恢复。
立即学习“前端免费学习笔记(深入)”;
- 提交开始时设
button.disabled = true,并记录原始文案(比如存到button.dataset.originalText) - 无论成功或失败,都必须执行恢复逻辑:
button.disabled = false+ 还原文案 - 避免用
loading...这类模糊提示,改成具体状态,如正在验证手机号...,降低用户焦虑
表单校验错误要透出到对应字段,别只弹个 alert
后端返回的字段级错误(如 { "email": ["邮箱已被注册"] })如果只用全局提示,用户根本找不到问题在哪。重点不是“展示错误”,而是“让错误可定位、可操作”。
- 遍历响应中的错误对象,用
form.querySelector('[name="email"]')找到对应输入框 - 在输入框旁插入
<small class="error">邮箱已被注册</small>,而不是覆盖原有提示 - 聚焦第一个出错字段:
input.focus(),但需加setTimeout避免被移动端键盘遮挡 - 清空旧错误提示再插入新提示,否则多次提交会堆叠多个
<small>



















