Saber 酱的抱枕

Fly me to the moon

07/7
2016
学习

JavaScript表单序列化

平时我们表单的提交多数是用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;");

JavaScript表单序列化