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的写法相差不多。但在扩展性上要好。

posted @ 2016-04-12 16:52  andrew-chen  阅读(570)  评论(0编辑  收藏  举报