jQuery.fn.serialize 阅读
今天第一次阅读jQuery源码,因为读到用js对表单的序列化,为的是在ajax操作中将表单中各个域的值传到服务器。书上用了很长的步骤,判断每一个表单域的属性,然后拼接。
大概是这样:
function serialize(form){ var parts = [], filed = null, i, len, j, ... for(i=0,len=form.elements.length;i<len;i++){ field=form.elements[i]; switch(field.type){ case "select-one": case "select-multiple": ... } } }
忽然想到jQuery应该是把这些封装的很好,就找来读了。第一次发现这种语言其实很优美,比Java简洁。
我开始有点喜欢上这门语言了 :)
一般我们是这样调用的
$('#dataform').serialize()
找了版本1.8.2的jQuery源码来读
function () { return jQuery.param(this.serializeArray()); }
最外层只调用了两个方法.jQuery.param()和jQuery对象本身的serializeArray(),从字面上理解就是
1.将表单本身序列化成数组
2.然后从中获得参数
分解如下:
1.先将表单本身序列化成数组
serializeArray()
1 function () { 2 return this.map(function () { 3 return this.elements ? jQuery.makeArray(this.elements) : this; 4 }).filter(function () { 5 return this.name && !this.disabled && (this.checked || rselectTextarea.test(this.nodeName) || rinput.test(this.type)); 6 }).map(function (i, elem) { 7 var val = jQuery(this).val(); 8 9 return val == null ? null : jQuery.isArray(val) ? jQuery.map(val, function (val, i) { 10 return { 11 name: elem.name, 12 value: val.replace(rCRLF, "\r\n") 13 }; 14 }) : { 15 name: elem.name, 16 value: val.replace(rCRLF, "\r\n") 17 }; 18 }).get(); 19 }
jQuery.map(callback)将一个数组"映射"成另一个数组,对其中每个元素调用callback方法。
接着返回表单中所有元素的数组。
必须有name,disabled为false,勾选上或是type包含在rinput之中。
取得过滤后元素的val,若val非null,再判断val是否是Array,对其中每个元素,返回一个对象,对象的name为元素的name,value为元素的val,并替换其中的制表符。
最后获取其中的数组。
所以这里看来,原先用js做的复杂switch判断都包含在了rselectTextarea.test(this.nodeName) || rinput.test(this.type)中,正则表达式果然强大。
具体就是这两个
/^(?:select|textarea)/i /^(?:color|date|datetime|datetimelocal|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i
哈哈,提到正则表达式,顺便给出刚搜到的幽默图片。
女:哦不!杀手肯定在假期里跟踪着她,但是要找到他们,我们必须要在200MB的邮件里找出像地址一类的东西!
男:没希望了!
程序员:众人闪开!我知道正则表达式。看我Perl大法!(啪啪键盘声)
好,现在我们回来继续看源码。
2.从数组中中获得参数
param()
1 function (a, traditional) { 2 var prefix, s = [], 3 add = function (key, value) { 4 // If value is a function, invoke it and return its value 5 value = jQuery.isFunction(value) ? value() : (value == null ? "" : value); 6 s[s.length] = encodeURIComponent(key) + "=" + encodeURIComponent(value); 7 }; 8 9 // Set traditional to true for jQuery <= 1.3.2 behavior. 10 if (traditional === undefined) { 11 traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional; 12 } 13 14 // If an array was passed in, assume that it is an array of form elements. 15 if (jQuery.isArray(a) || (a.jquery && !jQuery.isPlainObject(a))) { 16 // Serialize the form elements 17 jQuery.each(a, function () { 18 add(this.name, this.value); 19 }); 20 21 } else { 22 // If traditional, encode the "old" way (the way 1.3.2 or older 23 // did it), otherwise encode params recursively. 24 for (prefix in a) { 25 buildParams(prefix, a[prefix], traditional, add); 26 } 27 } 28 29 // Return the resulting serialization 30 return s.join("&").replace(r20, "+"); 31 }
定义数组s来存放字符串
定义add()来拼接key/value,如果value是方法,则调用,否则返回value值。将key和value编码后放入s
如果a是数组,那么假定a就是表单元素的集合。对其中所有元素调用add()。最后将s中所有字符串用&拼接。
总结:
按代码数来看,jquery写法与原生js的写法相差不多。但在扩展性上要好。