大黑 2019-06-25
Form
模块处理的是表单提交。表单提交包含两部分,一部分是格式化表单数据,另一部分是触发 submit
事件,提交表单。
读 Zepto 源码系列文章已经放到了github上,欢迎star: reading-zepto
本文阅读的源码为 zepto1.2.0
$.fn.serializeArray = function() { var name, type, result = [], add = function(value) { if (value.forEach) return value.forEach(add) result.push({ name: name, value: value }) } if (this[0]) $.each(this[0].elements, function(_, field){ type = field.type, name = field.name if (name && field.nodeName.toLowerCase() != 'fieldset' && !field.disabled && type != 'submit' && type != 'reset' && type != 'button' && type != 'file' && ((type != 'radio' && type != 'checkbox') || field.checked)) add($(field).val()) }) return result }
serializeArray
是格式化部分的核心方法,后面的 serialize
方法内部调用的也是 serializeArray
方法。
serializeArray
最终返回的结果是一个数组,每个数组项为包含 name
和 value
属性的对象。其中 name
为表单元素的 name
属性值。
add = function(value) { if (value.forEach) return value.forEach(add) result.push({ name: name, value: value }) }
表单的值交由 add
函数处理,如果值为数组(支持 forEach
) 方法,则调用 forEach
遍历,继续由 add
函数处理。否则将结果存入数组 result
中。最后返回的结果也是这个 result
。
if (this[0]) $.each(this[0].elements, function(_, field){ type = field.type, name = field.name if (name && field.nodeName.toLowerCase() != 'fieldset' && !field.disabled && type != 'submit' && type != 'reset' && type != 'button' && type != 'file' && ((type != 'radio' && type != 'checkbox') || field.checked)) add($(field).val()) })
如果集合中有多个表单,则只处理第一个表单的表单元素。this[0].elements
用来获取第一个表单所有的表单元素。
type
为表单类型,name
为表单元素的 name
属性值。
这一大段代码的关键在 if
中的条件判断,其实是将一些无关的表单元素排除,只处理符合条件的表单元素。
以下一个条件一个条件来分析:
field.nodeName.toLowerCase() != 'fieldset'
排除 fieldset
元素;!field.disabled
排除禁用的表单,已经禁用了,肯定是没有值需要提交的了;type != 'submit'
排除确定按钮;type != 'reset'
排除重置按钮;type != 'button'
排除按钮;type != 'file'
排除文件选择控件;((type != 'radio' && type != 'checkbox') || field.checked))
如果是 radio
或 checkbox
时,则必须要选中,这个也很好理解,如果没有选中,也不会有值需要处理。然后调用 add
方法,将表单元素的值获取到交由其处理。
$.fn.serialize = function(){ var result = [] this.serializeArray().forEach(function(elm){ result.push(encodeURIComponent(elm.name) + '=' + encodeURIComponent(elm.value)) }) return result.join('&') }
表单元素处理完成后,最终是要拼成如 name1=value1&name2=value2&...
的形式,serialize
方法要做的就是这部分事情。
这里对 serizlizeArray
返回的数组再做进一步的处理,首先用 encodeURIComponent
序列化 name
和 value
的值,并用 =
号拼接成字符串,存进新的数组中,最后调用 join
方法,用 &
将各项拼接起来。
$.fn.submit = function(callback) { if (0 in arguments) this.bind('submit', callback) else if (this.length) { var event = $.Event('submit') this.eq(0).trigger(event) if (!event.isDefaultPrevented()) this.get(0).submit() } return this }
处理完数据,接下来该到提交了。
if (0 in arguments) this.bind('submit', callback)
如果有传递回调函数 callback
,则在表单上绑定 submit
事件,以 callback
作为事件的回调。
else if (this.length) { var event = $.Event('submit') this.eq(0).trigger(event) if (!event.isDefaultPrevented()) this.get(0).submit() }
否则手动绑定 submit
事件,如果没有阻止浏览器的默认事件,则在第一个表单上触发 submit
,提交表单。
注意 eq
和 get
的区别, eq
返回的是 Zepto
对象,而 get
返回的是 DOM
元素。
署名-非商业性使用-禁止演绎 4.0 国际 (CC BY-NC-ND 4.0)
最后,所有文章都会同步发送到微信公众号上,欢迎关注,欢迎提意见:
作者:对角另一面