必须拦截默认提交并用 javascript 重写发送逻辑才能实现自定义数据格式;通过 event.preventdefault() 阻止原生提交,用 formdata 提取字段后重组,再用 fetch 发送 json、url 编码或 multipart 格式,并确保前后端解析方式一致。

直接改 form 的 action 和 method 只能控制目标和请求类型,无法改变提交数据的格式;真正实现自定义格式(比如 JSON、URL 编码以外的结构、带签名字段、多部分混合体),必须拦截默认提交并用 JavaScript 重写发送逻辑。
用 event.preventDefault() 阻止原生提交
表单默认会把 name=value 键值对按 application/x-www-form-urlencoded 或 multipart/form-data 发送,没法塞进 JSON 字段或加时间戳。所以第一步永远是阻止它:
- 在
form上绑定onsubmit="return false;",或更推荐:用addEventListener('submit', ...) - 回调里第一句必须是
event.preventDefault(),否则浏览器仍会跳转或发原生请求 - 别只靠
return false—— 它不阻止事件冒泡,也不兼容所有场景,preventDefault()才是确定性拦截
用 FormData 提取原始字段再重组
FormData 是读取表单当前值最可靠的方式,尤其支持文件上传,但它输出的是键值对,不是 JSON。你需要手动提取再包装:
- 创建实例:
const fd = new FormData(formElement) - 遍历获取所有字段:
for (const [key, value] of fd.entries()) { ... } - 若要发 JSON,得构造新对象:
const payload = { timestamp: Date.now(), data: Object.fromEntries(fd) } - 注意:文件 Blob 不能直接 JSON.stringify,需用
fd.append()保持 multipart,或转为 base64 后塞进 JSON(但体积大、后端要适配)
用 fetch 发送自定义格式请求
fetch 能完全控制请求头和 body,是替换原生提交的核心工具:
- 发 JSON:
headers: { 'Content-Type': 'application/json' },body 传JSON.stringify(payload) - 发标准表单编码(但加额外字段):
body: new URLSearchParams({ ...fdObject, sign: 'xxx' }) - 发 multipart(含文件+文本):
body: fd,此时不要设Content-Type—— 浏览器会自动生成带 boundary 的 header - 错误容易出在:手动设了
Content-Type却又传FormData,导致 boundary 丢失,后端收不到文件
后端接收逻辑必须同步适配
前端格式一变,后端解析方式就得跟着变,这点常被忽略:
- 如果前端发 JSON,后端不能再用
req.body.username(Express 默认不解析 JSON),要确保有express.json()中间件 - 如果前端用
URLSearchParams发字符串,后端需按 query string 解析,而非 form body - 如果混用字段(如 JSON 里嵌一个 base64 文件),后端得自己 decode 并存文件,不能依赖框架的 multipart 处理器
- 跨域时,自定义
Content-Type(如application/json)会触发预检请求(OPTIONS),后端必须正确响应,否则请求直接失败
真正难的不是拼出 JSON 或调用 fetch,而是前后端对“这个请求到底长什么样”有一致约定,并且所有中间层(CDN、WAF、反向代理)都不篡改或丢弃你自定义的字段和头信息。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











