平时我们表单的提交多数是用action来指定提交到的文件,但这样会产生页面的刷新。用ajax提交可以避免刷新,但是需要我们自己组织要提交的数据。这就是表单序列化了。
jQuery有个serialize方法来做表单序列化,语法如下:
$(selector).serialize();
序列化之后,表单里需要提交的值会被组织成字符串,形如:
"name=124&company=baidu.com&fav=1,2,3"
如果里面有汉字之类,会自动进行url编码。表单序列化完全模拟了浏览器提交时的数据,这样我们就可以用ajax来提交表单了。
如一个id为“yy”的表单,它的提交的地址是"/plus/diy.php",提交按钮id是submit。那么表单序列化并提交的代码如下:
$("#submit").click(function(event) {
event.preventDefault();
$.ajax({
type: "post",
url: "/plus/diy.php",
data: $("#yy").serialize(),
success: function() {
alert("信息提交成功。");
}
})
})
注意用preventDefault()阻止浏览器默认事件(就是跳转到action页面,即使你没写action属性也会跳转的)。
后台对提交数据的处理和用action提交时的数据是一致的。
下面是用原生JavaScript代码定义的表单序列化函数serialize。
function serialize(form) {
var parts = [],
field = null,
i,
len,
j,
optLen,
option,
optValue;
for (i = 0, len = form.elements.length; i < len; i++) {
field = form.elements[i];
switch (field.type) {
case "select-one":
case "select-multiple":
if (field.name.length) {
for (j = 0, optLen = field.options.length; j < optLen; j++) {
option = field.options[j];
if (option.selected) {
optValue = "";
if (option.hasAttribute) {
optValue = (option.hasAttribute("value") ?
option.value : option.text);
} else {
optValue = (option.attributes["value"].specified ?
option.value : option.text);
}
parts.push(encodeURIComponent(field.name) + "=" +
encodeURIComponent(optValue));
}
}
}
break;
case undefined: //字段集
case "file": //文件输入
case "submit": //提交按钮
case "reset": //重置按钮
case "button": //自定义按钮
break;
case "radio": //单选按钮
case "checkbox": //复选框
if (!field.checked) {
break;
}
/* 执行默认操作 */
default:
//不包含没有名字的表单字段
if (field.name.length) {
parts.push(encodeURIComponent(field.name) + "=" +
encodeURIComponent(field.value));
}
}
}
return parts.join("&");
}
下面放个用原生XMLHttpRequest对象发送post异步请求的完整代码:
// function serialize(form)... 由于行数过长,此处省略具体代码,请自行引入serialize函数
var e = event || window.event; //firefox里的event是临时的,不是window下的全局变量
e.preventDefault ? e.preventDefault() : e.returnValue = false; //阻止浏览器默认事件(跳转)
var postdata = serialize(document.querySelector("#form1")); //序列化表单
var xhr = new XMLHttpRequest(); //创建XMLHttpRequest对象
xhr.onreadystatechange = function() { //监听XMLHttpRequest请求状态
if (xhr.readyState === 4) { //XMLHttpRequest请求已完成
if (xhr.status === 200) { //如果返回的状态码为200
console.log(xhr.responseText);
alert("数据提交成功");
} else {
console.log("发生了异常,状态码为" + xhr.status + "," + xhr.statusText);
}
}
}
xhr.open("post", "/t/t.php", true); //打开XMLHttpRequest连接,url修改为自己用的
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;"); //用post的时候一定要有这句,此句规定提交数据的格式。这个Content-Type适用不带附件的form表单;multipart/form-data适用于文件上传,text/plain则将数据以纯文本形式进行编码,其中不含任何控件或格式字符
xhr.send(postdata); //发送XMLHttpRequest请求
今天我实际使用这个方法的时候,一开始不知道要加Content-Type,搞得我花了半个多小时才找到问题。就是下面这句:
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;");