Form
模塊處理的是表單提交。表單提交包含兩部分,一部分是格式化表單數據,另外一部分是觸發 submit
事件,提交表單。javascript
讀 Zepto 源碼系列文章已經放到了github上,歡迎star: reading-zeptojava
本文閱讀的源碼爲 zepto1.2.0node
《reading-zepto》git
$.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
方法。github
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)
最後,全部文章都會同步發送到微信公衆號上,歡迎關注,歡迎提意見:
做者:對角另外一面