木灵鱼儿
阅读:3788
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];即可,其他不动。
调用方法则和开头写的一样,这里就不重复了。
版权申明
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿 - 有梦就能远航站点。未经许可,禁止转载。

相关推荐
第四章 对象的创建
命名空间在ESM模块化还未出来之前,用于减少全局变量名污染的一种做法就是使用命名空间,其做法也非常简单,就是创建一个全局的变量,然后将内容都赋值给这个变量,从而减少对全局变量的使用。//创建命名空间 var MYAPP = {}; //构造函数 MYAPP.Parent = function(){}; MYAPP.Child = function(){}; // 一个变量 MYAPP.some_var =1; // 一个对象容器 MYAPP.modules ={}; // 嵌套的对象 MYAPP.modules.module1 ={}; MYAPP.modules.module1...
对象扁平化
前言后端返回给前端的数据,有时候会是一个多层级对象,但是我们前端使用的时候,for循环遍历渲染时,多层级对象往往需要进行单独处理,因为还需要判断这个key值是否存在,否则会报错。强行让后端改变数据结构又好像不现实,无奈,只有自己处理了。掘金看到一位大佬文章《【算法】JS 实现对象的扁平化》感觉很合适,逻辑清晰。要求将对象中的层级扁平化,改成如下格式:// 实现一个 flatten 函数,实现如下的转换功能 const obj = { a: 1, b: [1, 2, { c: true }], c: { e: 2, f: 3 }, g: null, }; // 转换为 l...
vue骚操作之重置data对象
简单说下使用场景,你使用一个dialog组件,弹窗时要加载数据,关闭后要清理数据,以防下次使用报错或者数据残留,如果在data中写了过多的属性,或者层级很深的引用对象啥的,为了方便还原,你可能会一个个的写。onClose() { this.xxx = xxx; this.xxx.xxx = xxx; this.xxx.xxx = xxx; this.xxx.xxx = xxx; }对多个值进行赋值操作。但是,这样实在是太难了,有没有一种简单的方法,就像表单重置一样。答案当然是有的:onClose() { Object.assign(this.$data, this.$...
JSON 格式化对象,对象中存在函数的解决办法,JSON格式化函数
json在格式化对象是,如果是普通的键值对对象还是没有问题的,但是如果他的值是一个函数,在格式化之后,函数就会被剔除。const a = { name: '我爱你', fn: function(){ console.log("我也爱你!") } }; const b = JSON.stringify(a);当你输出变量b的时候,你得到的会是:"{\"name\":\"我爱你\"}"fn不见了!引用JSON.stringify()方法描述中的一段解释:undefined、任意的函数以及 s...
fetch 请求报错处理思路
之前写过一片使用fetch下载文件的方法,但是如果后端返回一个错误对象,使用response.blob()会将这个错误对象直接转为blob对象,然后被转为文件下载下来。但实际上我们是要区分处理的,比如是文件流我们就下载文件,是错误对象,我们就进行错误提示和抛出错误。所以这里,我主要分享下我对错误处理的思路。基础知识首先,在fetch第一个then回调中,我们可以对response对象进行三种方法操作:response.text 返回的是一个纯文本 是一个promise对象response.json 返回的是一个对象(json/array) 是一个promise对象response.b...

获取元素距离顶部的距离
这个方法太常用了,写个笔记 //获取顶部距离 function getTop(element) { let realTop = element.offsetTop; let parent = element.offsetParent; while (parent !== null) { realTop += parent.offsetTop; parent = parent.offsetParent; } return realTop; },接收原生dom对象
git 删除远程分支某个文件或者某个文件夹
经常遇到这种情况,不小心上传了某个文件,这个文件是不需要上传到远程仓库,很头疼。本地的又不想删除,想着直接删除远程,百度半天都没找到好用的,最后问了下群友,给了个教程链接,我研究了下,大概明白怎么回事。首先为了防止本地的再次被上传,需要配置本地白名单,白名单的话,以vue项目为例子,在项目根目录有一个.gitignore文件,没有就自己创建一个,然后里面直接填目录或者文件名就行了。/dist /xxx.js本地白名单之后,以后git上传都不会上传该文件。现在我们要处理远程仓库的文件首先我们需要删除git在缓存中的文件git rm --cached config.js //删除conf...
Object 对象的扩展
属性的简写es6允许对属性进行简写,可以直接使用变量,变量名直接成为了属性名。var a = "hello"; var b = {a}; //等同于 var b = { a:a }属性里的方法也可以简写var a = { b(){...} } //等同于 var a = { b: function(){ ... } }在CommonJS模块输出变量时,也就是node模块导出时,这种简写就显得十分方便,我们直接导致一个对象,对象里面使用简写。var a = {}; var b = {}; module.exports = {a,b}而属性的赋...
Function 函数
函数默认参数es5无法设置默认参数,只能通过函数内部先进行判断,如果没有参数则设置一个值。function test(x,y){ x = x || "hello "; y = y || "word"; console.log(x+y); } test(); //hello word这样写的话会有一个问题,就是如果我就要参数为空,就会出现问题test("","test"); // hello test所以我们还需要加一个判断function test(x,y){ x = typeof x...
Alex
Google Chrome Windows 7你好,很佩服你的毅力,我也是自学js基础,看了不少视频,最后看的李炎恢JS封装项目。我也是跟着做了一半最后我放弃了。目前正在学习前端框架angular和后端的node.js.加油。。前端涉及的东西很多。希望有机会可以互相分享和学习。
木灵鱼儿
FireFox Windows 10我也是看李炎恢这个,但是感觉学了很多其实忘了也很多,js我估计还要再看看一些基础教程和项目实践才行