今天第一次閱讀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的寫法相差不多。但在擴展性上要好。