前言JavaScript最初的应用场景之一就是分担服务端处理表单的责任,打破处处依赖服务端的局面。本文主要介绍zepto中表单模块的几个方法,表单处理,serialize,serializeArray,submit。原文链接GitHub项目地址表单相关回顾在开始学习表单模块相关的一些方法之前,先回顾一下表单提交时浏览器是如何向服务器发送数据的(以下内容摘自第14章14.4节表单序列化)URL-编码表单字段的名称和值,用&分隔。不发送禁用的表单域。(即disabled属性为true)只发送checked的checkbox和radiobutton,type为reset和button的按钮不发送这种情况下submit按钮的值也会被发送,否则提交按钮将不会被发送。select元素的值是所选option元素的value属性的值。如果option元素没有value属性,则它是option元素的文本值。在表单序列化过程中,一般不包含任何按钮字段,因为生成的字符串很可能通过其他方式提交,需要遵循其他规则。有了以上知识的复习,接下来我们开始看zepto中serialize和serializeArray的实现。serializeArray因为serialize依赖于serializeArray的实现,所以我们来看看它是如何实现的。而他的作用就是将表单form序列化为一个由name和value属性组成的对象数组。如:[{name:'qianlongo',value:'haha'},{name:'wangmin',value:'heihei'}]sourcecode$.fn.serializeArray=function(){varname,type,result=[],add=function(value){如果(value.forEach)returnvalue.forEach(add)result.push({name:name,value:value})}if(this[0])$.each(this[0].elements,function(_,field){type=field.type,name=field.nameif(name&&field.nodeName.toLowerCase()!='fieldset'&&!field.disabled&&类型!='提交'&&type!='reset'&&type!='button'&&type!='file'&&((type!='radio'&&type!='checkbox')||field.checked))add($(field).val())})returnresult}在$的原型中添加了serializeArray相关的方法。一开始声明了named、type、result三个变量,分别存放了表单控件的name属性和type属性,最后是函数执行后要返回的数组。首先用this[0]判断有未选中的表单元素。如果没有返回结果,它将是一个空数组。如果选中,则遍历表单的相关控件(form.elements代表表单中所有控件的集合)。获取单个控件的类型(type)和名称属性(name),进而判断是否满足提交给服务器的表单控件的条件。它需要有一个名称属性(条件为“真”)。它不能是字段集元素。它不能是已被禁止的元素(即disable为true)。它不能是提交、重置、按钮或文件等元素。对于单选和多选控件,只发送勾选的。当满足上述条件时,调用add函数,传入通过$(elements).val()得到的值。add函数的逻辑也很简单。如果value是一个数组,则将value数组的每个递归项传递给add。要么是一个数组,要么直接以{name:name,value:value}的形式推送结果。但是这个值什么时候会是一个数组呢?我们需要从zepto模块的val函数实现中看出,val函数实现了functionval(value){if(0inarguments){if(value==null)value=""returnthis.each(function(idx){this.value=funcArg(this,value,idx,this.value)})}else{//主要看这里,multiple用来设置下拉列表是否可以多选。//如果是多选,选中选中的(即selected为true)元素,通过pluck方法读取元素的值,最后返回一个数组returnthis[0]&&(this[0].multiple?$(this[0]).find('option').filter(function(){returnthis.selected}).pluck('value'):this[0].value)}}serialize将形成内容被序列化为查询字符串。类似于name=qianlongo&sex=boy源码$.fn.serialize=function(){varresult=[]this.serializeArray().forEach(function(elm){//每个形式的name和value通过encodeURIComponent编码result.push(encodeURIComponent(elm.name)+'='+encodeURIComponent(elm.value))})//最后返回result.join('&')}用&符号分隔。在serializeArray的基础上,serialize就是将对应的name和value都进行encodeURIComponent编码,然后用&符号分隔,就达到了我们想要的结果。提交有两种用法。当传入一个回调函数时,就是给指定表单的提交事件添加一个回调处理函数。如果没有传入回调函数,则触发当前表单的提交事件,执行提交表单的默认行为(前提是浏览器的默认行为没有被屏蔽)。源码$.fn.submit=function(callback){//如果传递了回调函数,则给被选元素添加一个提交事件if(0inarguments)this.bind('submit',callback)//否则,如果没有传递回调函数,并且选择了一个表单元素elseif(this.length){varevent=$.Event('submit')//提交事件触发第一个选择的表单。注意这里只是手动触发绑定的提交事件,不会提交表单this.eq(0).trigger(event)//如果默认事件没有被拦截,调用form.submit()提交formif(!event.isDefaultPrevented())this.get(0).submit()}returnthis}以上是文末zeptoform模块相关源码分析,欢迎指正。文章记录了表单模块zepto源码分析,表单模块zepto模块,Zepto中的这些实用方法集,Zepto核心模块的工具和方法,event模块,为什么mouseenter和mouseover这么纠结?学习如何从zepto.js手动触发DOM事件谁说你只是“会用”jQuery?ajax模块,你就是这样的jsonp(原理和具体实现细节)
