web表单提交和表单序列化的多种方式总结
声明:本文主要内容来自夸克。
Web表单提交的几种方式
1. HTML表单提交(Form Submission)
- 使用
<form>
标签,通过设置method="GET"
或method="POST"
来提交数据。 - GET:将数据附加在URL后,适合非敏感、小量数据(如搜索、分页)。
- POST:将数据放在请求体中,适合敏感或大量数据(如登录、注册)。
2. AJAX提交(Asynchronous JavaScript and XML)
- 使用JavaScript的
XMLHttpRequest
或fetch API
异步发送数据,无需刷新页面。 - 适用于局部更新、动态交互场景(如实时搜索、表单验证)。
3. WebSocket提交
- 建立持久化全双工连接,实现客户端与服务器实时双向通信。
- 适用于聊天应用、在线游戏等需要实时交互的场景。
4. RESTful API / GraphQL
- 通过HTTP方法(GET、POST、PUT、DELETE等)操作资源,前端发送结构化请求至后端API。
- 适用于前后端分离架构,提升接口规范性与灵活性。
综上,主流提交方式包括:HTML表单、AJAX、WebSocket 和 RESTful API/GraphQL,选择依据具体业务场景和交互需求。
web表单不同提交方式的参数格式
1. GET请求参数格式
- URL查询字符串(Query String)
- 格式:
key1=value1&key2=value2
- 参数附加在URL后,以
?
开始,多个参数用&
连接 - 例如:
http://example.com/page?name=John&age=25
- 通常用于非敏感、小量数据传输
- 格式:
2. POST请求参数格式
2.1 application/x-www-form-urlencoded
- 键值对形式,格式和URL查询字符串类似
- 例如:
username=zhangsan&password=123456
- 默认的表单提交格式,兼容性好,适合普通文本数据
- 注意默认情况下,对服务器而言,post请求与提交表单是不一样的。
2.2 multipart/form-data
- 可包含文件和键值对,用分隔符boundary分开
- 主要用于文件上传或表单中包含二进制数据
- 请求体中每个部分以
--boundary
隔开,末尾以--boundary--
结束 -
在处理包含文件上传的Web表单时,通常需要使用
multipart/form-data
作为表单的编码类型。这是因为multipart/form-data
允许表单同时传输文本数据和二进制文件数据,而其他编码方式(如application/x-www-form-urlencoded
)则不支持直接传输文件。-
<form id="myForm" action="#" method="post" enctype="multipart/form-data">
-
- 注意监听change事件然后遍历files集合可以取得每个选中文件的信息。
-
示例
-
window.URL.createObjectURL
-
window.URL.createObjectURL(),传入File或Blob对象,函数返回值是一个指向内存中地址的字符串。因为这个字符串是URL,所以可以在DOM中直接使用。
//监听change事件然后遍历files集合可以取得每个选中文件的信息。
document.querySelector("input[type=file]").addEventListener("change", function (e) {var files = e.target.files;for (var i = 0, file = files[i]; i < files.length; i++) {var info = ["文件名: " + file.name, "文件大小: " + file.size, "最后修改时间: " + file.lastModifiedDate].join("\n");console.log(info);}
});//使用对象URL在页面中显示一张图片
document.querySelector("input[type=file]").addEventListener("change", function (e) {let output = document.querySelector("#output"),files = e.target.files,//创建对象URL// window.URL.createObjectURL(),传入File或Blob对象,函数返回值是一个指向内存中地址的字符串。因为这个字符串是URL,所以可以在DOM中直接使用。url = window.URL.createObjectURL(files[0]);//console.log(files);if (url) {if (/image/.test(files[0].type)) {output.innerHTML = `<img src="${url}" alt="图片预览">`;} else {output.innerHTML = "选择的不是图片!";}} else {output.innerHTML = "当前浏览器不支持URL!";}
});
2.3 application/json
- JSON字符串格式,可表达复杂数据结构
- 例如:
{"name":"John","age":25}
- 越来越多用于前后端分离、RESTful接口,需后端支持解析JSON
- 注意JSON和对象在格式上的区别,以及JSON和JavaScript对象之间的相互转换。
- 与JavaScript对象字面量相比,JSON主要有两处不同:
-
最后没有分号(不需要,因为不是JavaScript语句)
- 没有变量声明(JSON中没有变量)
-
- JSON对象有两个方法
- JSON.stringify()
-
JSON.parse()
2.4 text/xml
- XML格式数据,用作远程调用(XML-RPC),结构较臃肿,现较少用
3. 其他方式
- 通过AJAX或Fetch API提交:可自定义参数格式,通常用JSON。
- WebSocket:以消息形式发送数据,格式灵活(字符串、JSON等)
总结:
- GET请求参数为URL键值对;
- POST请求有多种格式:urlencoded(文本键值对)、multipart/form-data(文件和文本)、JSON(复杂结构)、XML(已较少用)。
表单序列化
Web表单序列化通常用于将表单数据转换为字符串格式,以便通过HTTP请求发送到服务器。常见的表单序列化方式包括以下几种:
- application/x-www-form-urlencoded
- 这是最常用的表单提交类型。它会将表单字段和值编码成键值对的形式,并用
&
分隔不同的键值对。特殊字符会被转义。 -
表单在JavaScript中可以使用表单字段type、name、value属性来进行序列化。
理解浏览器如何确定在提交表单时要把什么发送到服务器。
- 字段名和值是URL编码的并以和号(&)分隔。
- 禁用字段不会发送。
- 复选框或单选按钮只在被选中时才发送。
- 类型为reset或button的按钮不会发送。
- 多选字段的每个选中项都有一个值。
- 通过点击提交按钮提交表单时,会发送该提交按钮。否则,不会发送提交按钮。类型为image的<input>元素视同提交按钮。
- <select>元素的值是被选中<option>元素的value属性。如果<option>没有value属性,则该值是它的文本。
- 这是最常用的表单提交类型。它会将表单字段和值编码成键值对的形式,并用
- multipart/form-data
- 当表单中包含文件上传控件时,必须使用此类型。这种格式不会对数据进行编码,而是以二进制流的方式发送数据,每个部分都有自己的边界。
- text/plain
- 此种类型很少使用,因为它不会对特殊字符进行编码,这可能导致服务器端解析问题。
- JSON
- 尽管不是标准的表单提交类型,但可以通过JavaScript手动将表单数据转换为JSON格式,然后通过AJAX请求发送。
使用XHR模拟表单提交
默认情况下,对服务器而言,post请求与提交表单是不一样的。
服务器逻辑需要读取原始post数据才能取得浏览器发送的数据。
可以使用XHR模拟表单提交,需要把Content-Type头部设置为”application/x-www-formurllencoded”,且创建对应格式的字符串。post数据此时使用与查询字符串相同的格式。
xhr.setRequestHeaders(“Content-Type”,”application/x-www-formurllencoded”);
如果网页中确实有一个表单需要序列化并通过XHR发送到服务器,可以使用serialize()函数来创建相应的字符串。
serialize()函数
function serialize(form) {let parts = []; //存储字段let optValue; //存储字段值for (let field of form.elements) {//遍历所有字段//switch语句在比较每个条件的值时会使用全等操作符,因此不会强制转换数据类型(比如,字符串“10”不等于数值10)。switch (field.type) {case "select-one": //单选框 //没有break(连续匹配多个条件),继续匹配下一个条件。单选框或者多选框的选项case "select-multiple": //多选框if (field.name.length) {//存在字段名for (let option of field.options) {//遍历所有选项if (option.selected) {//选中// 修复:正确检查 value 属性是否存在if (option.hasAttribute && option.hasAttribute("value")) {//DOM合规的浏览器optValue = option.value;} else if (option.attributes && option.attributes["value"] && option.attributes["value"].specified) {//IE8及以下optValue = option.value;} else {optValue = option.text;}parts.push(encodeURIComponent(field.name) + "=" + encodeURIComponent(optValue));}}}break; //跳出switch 使程序终止循环,执行后面的语句,常与if,switch一起使用。case undefined: //字段集 <fieldset>没有type属性 type属性是undefined 不必纳入序列化case "file": //文件上传case "reset": //重置case "submit": //提交case "button": //按钮break;case "radio": //单选框case "checkbox": //复选框if (!field.checked) {break;}default: //default 关键字定义在任何条件都不匹配时执行的语句。前面执行的case后面没有break也会执行default。if (field.name.length) {//忽略没有name属性的元素parts.push(encodeURIComponent(field.name) + "=" + encodeURIComponent(field.value));}}}return parts.join("&");
}
FormData
现代web应用程序中经常需要对表单数据进行序列化,因此XMLHttpRequest Level 2新增了FormData类型,便于表单序列化。
FormData对象的append()方法接收两个参数:键和值,相当于表单中的字段和其值。
通过直接给FormData构造函数传入一个表单元素,可以将表单中的数据作为键值对填充进去。
var formData = new FormData(document.forms[0]);
//xhr.send(formData);
使用FormData不再需要给XHR对象显式设置任何请求头部。
XHR对象能够识别作为FormData实例传入的数据类型并自动配置相应的头部。
URLSearchParams
URLSearchParams 是一个用于处理 URL 查询参数的接口。
它提供了一种简单的方法来操作 URL 中的查询字符串部分。
详见之前文章
URLSearchParams :处理 URL 查询参数的接口