您的位置:首页 - 教程 - jQuery - 正文
jQuery.fn.serialize 阅读与原生js比对

今天第一次阅读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()

 function () {
     return this.map(function () {
         return this.elements ? jQuery.makeArray(this.elements) : this;
     }).filter(function () {
         return this.name && !this.disabled && (this.checked || rselectTextarea.test(this.nodeName) || rinput.test(this.type));
     }).map(function (i, elem) {
         var val = jQuery(this).val();
 
         return val == null ? null : jQuery.isArray(val) ? jQuery.map(val, function (val, i) {
             return {
                 name: elem.name,
                 value: val.replace(rCRLF, "\r\n")
             };
         }) : {
             name: elem.name,
             value: val.replace(rCRLF, "\r\n")
         };
     }).get();
 }

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()

 function (a, traditional) {
     var prefix, s = [],
         add = function (key, value) {
         // If value is a function, invoke it and return its value
         value = jQuery.isFunction(value) ? value() : (value == null ? "" : value);
         s[s.length] = encodeURIComponent(key) + "=" + encodeURIComponent(value);
     };
 
     // Set traditional to true for jQuery <= 1.3.2 behavior.
     if (traditional === undefined) {
         traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
     }
 
     // If an array was passed in, assume that it is an array of form elements.
     if (jQuery.isArray(a) || (a.jquery && !jQuery.isPlainObject(a))) {
         // Serialize the form elements
         jQuery.each(a, function () {
             add(this.name, this.value);
         });
 
     } else {
         // If traditional, encode the "old" way (the way 1.3.2 or older
         // did it), otherwise encode params recursively.
         for (prefix in a) {
             buildParams(prefix, a[prefix], traditional, add);
         }
     }
 
     // Return the resulting serialization
     return s.join("&").replace(r20, "+");
 }

定义数组s来存放字符串

定义add()来拼接key/value,如果value是方法,则调用,否则返回value值。将key和value编码后放入s

 

如果a是数组,那么假定a就是表单元素的集合。对其中所有元素调用add()。最后将s中所有字符串用&拼接。

 

总结:

按代码数来看,jquery写法与原生js的写法相差不多。但在扩展性上要好。


评论: