Ajax 表单序列化
什么是表单序列化呢?
将所有表单的提交通过一个标准化的方法去获取并且提交出去,那就是序列化,也就是说不同的表单,如注册啊,登录啊,修改资料啊,这些东西可以通过一个通用的方法去处理它。
那么表单序列化有几个要求:
- 不能发送禁用的表单字段;
- 只发送勾选的复选框和单选按钮;
- 不发送type是reset、submit、file、button以及字段集;
- 多选选择框中的每个选中的值单独一个条目;
- 对于select元素,如果有value值,就指定value作为发送的字段,如果没有,就指定text值;
已经将ajax的代码作为单独的一个文件保存,而调用则使用ajax()的方法,之前也做了一个表单提交的方法,在所有条件都是ture的时候才调用 submit()方法提交表单,但是我们使用ajax表单序列化则不使用这个方法,而是使用ajax()方法来提交;
if (flage) {
ajax({
method: 'post',
url: 'demo3.php',
data: $('#reg_form').serialize(),
success: function(text) {
alert(text);
},
async: true
});
}
data的值则是获取到表单提交的字段,并转为键值对的对象保存,然后ajax提交出去。
$('#reg_form').serialize() 这句就是获取到表单里面的内容的,方法则是使用serialize方法,这里我是直接写的固定id,实际上应该要通过方法来获取当前表单的,这里以后再说。
那先写serialize的方法
function serialize(form) {
var pre = {};
for(var i = 0;i<form.elements.length;i++){
var filed = form.elements[i];
switch(filed.type) {
case undefined :
case 'reset' :
case 'submit' :
case 'file' :
case 'button' :
break;
case 'radio' :
case 'checkbox'
if(!filed.selected) break;
default :
pre[filed.name] = filed.value;
}
}
return pre;
}
这里传入的form就是表单元素,pre就是创建的一个空对象,用来保存键值对,通过for循环,将表单里面的元素一个个判断,通过switch方法判断,如果是当前元素的type值是undefined,说明当前元素被禁用,如果是reset、submit、file、button,这几个共用一个break,如果是radio和checkbox共用一个if(!filed.selected) break; 反之以上都不是,说明是可以正常获取到值的,通过pre[filed.name] = filed.value;的方式,将name和value保存在pre对象中。
但是这里还差一个select元素,这个元素有两种type值,一种是单选的,如问题,年月日这些都是单选的,他的type值为select-one,那如果是多选的,type值为select-multiple;既然都是select元素,那么也可以共用同一个方法,加上都是选项,自然会有个多个选项,for循环肯定要有
case 'select-one' :
case 'select-multiple' :
for(var j = 0;j<filed.options.length;j++) {
var option = filed.options[j];
if(option.selected){
var opValue = '';
if(option.hasAttrbute) {
opValue = option.hasAttrbute('value') ? option.value : option.text;
}else {
opValue = option.attributes('value').specified ? option.value : option.text;
}
pre[filed.name] = opValue;
}
}
for循环一遍select中的所有option元素,如果这个option被选择了(option.selected),那么就判断,这个元素有没有value值,如果有,返回value值,如果没有,返回text值。
一般来说,value是通用属性,一般都是返回input元素中用户填入的值,但是选项就不一样了,选项是固定的值,value的值一般都是事先写在html上的,但也有可能没有写。
text属性是option元素的属性,返回的是设置的值:
<option>我就是text属性获得的值</option>
value的值我们有可能没有设置,那么就要获得text的值,但是ie和其他浏览器没有一个可以通杀的方法来判断到底设没设置value的值,所以还要做个兼容。
hasAttrbute这个方法是ie8及以上和其他浏览器支持,attributes是旧方法,它单独使用:option.hasAttrbute;这样是获取option元素里面所有的属性集合,option.hasAttrbute(‘value’);这样则是单独获取value的属性,再通过specified来判断value是否有值,如果没有,则返回text。
value和text的属性所有浏览器都是支持的,只是判断value是否有值,旧版本ie就不能使用hasAttrbute来判断。
判断好后,将值赋给opValue,然后在传给pre对象。
整合一下:
function serialize(form) {
var pre = {};
for (var i = 0; i < form.elements.length; i++) {
var filed = form.elements[i];
switch (filed.type) {
case undefined:
case 'reset':
case 'submit':
case 'file':
case 'button':
break;
case 'radio':
case 'checkbox'
if (!filed.selected) break;
case 'select-one':
case 'select-multiple':
for (var j = 0; j < filed.options.length; j++) {
var option = filed.options[j];
if (option.selected) {
var opValue = '';
if (option.hasAttrbute) {
opValue = option.hasAttrbute('value') ? option.value : option.text;
} else {
opValue = option.attributes('value').specified ? option.value : option.text;
}
pre[filed.name] = opValue;
}
}
default:
pre[filed.name] = filed.value;
}
}
return pre;
}
调用:
serialize($('#reg_form').first());
这样就差不多了,我们再将他整合成一个插件,之前的插件入口是:
//插件入口
Base.prototype.extend = function(name,fn) {
Base.prototype[name] = fn;
}
于是:
//表单序列化
$().extend('serialize',function(){
for(var i = 0;i<this.arr.length;i++) {
var form = this.arr[i];
var pre = {};
for(var i = 0;i<form.elements.length;i++){
var filed = form.elements[i];
switch(filed.type){
case undefined :
case 'submit' :
case 'reset' :
case 'file' :
case 'button' :
break;
case 'radio' :
case 'checkbox' :
if (!filed.selected) break;
case 'select-one' :
case 'select-multiple' :
for(var j = 0;j<filed.options.length;j++){
var option = filed.options[j];
if(option.selected) {
var opValue = '';
if(option.hasAttribute) {
opValue = option.hasAttribute('value') ? option.value : option.text;
}else {
opValue = option.attributes('value').specified ? option.value : option.text;
}
pre[filed.name] = opValue;
}
}
default :
pre[filed.name] = filed.value;
}
}
return pre;
}
return this;
});
form元素不用通过传参的方式获取,而是通过this.arr[i]的方式获取到了,所以做个一个var form = this.arr[i];即可,其他不动。
调用方法则和开头写的一样,这里就不重复了。
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿站点。未经许可,禁止转载。
全部评论 2
Alex
Google Chrome Windows 7木灵鱼儿
FireFox Windows 10