Form
模組處理的是表單提交。表單提交包含兩部分,一部分是格式化表單資料,另一部分是觸發 submit
事件,提交表單。
讀 Zepto 原始碼系列文章已經放到了github上,歡迎star: reading-zepto
原始碼版本
本文閱讀的原始碼為 zepto1.2.0
GitBook
.serializeArray()
$.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
方法。
serializeArray
最終返回的結果是一個陣列,每個陣列項為包含 name
和 value
屬性的物件。其中 name
為表單元素的 name
屬性值。
add函式
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
方法,將表單元素的值獲取到交由其處理。
.serialize()
$.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
方法,用 &
將各項拼接起來。
.submit()
$.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
元素。
系列文章
- 讀Zepto原始碼之程式碼結構
- 讀Zepto原始碼之內部方法
- 讀Zepto原始碼之工具函式
- 讀Zepto原始碼之神奇的$
- 讀Zepto原始碼之集合操作
- 讀Zepto原始碼之集合元素查詢
- 讀Zepto原始碼之操作DOM
- 讀Zepto原始碼之樣式操作
- 讀Zepto原始碼之屬性操作
- 讀Zepto原始碼之Event模組
- 讀Zepto原始碼之IE模組
- 讀Zepto原始碼之Callbacks模組
- 讀Zepto原始碼之Deferred模組
- 讀Zepto原始碼之Ajax模組
- 讀Zepto原始碼之Assets模組
- 讀Zepto原始碼之Selector模組
- 讀Zepto原始碼之Touch模組
- 讀Zepto原始碼之Gesture模組
- 讀Zepto原始碼之IOS3模組
- 讀Zepto原始碼之Fx模組
- 讀Zepto原始碼之fx_methods模組
- 讀Zepto原始碼之Stack模組
附文
參考
License
署名-非商業性使用-禁止演繹 4.0 國際 (CC BY-NC-ND 4.0)
最後,所有文章都會同步傳送到微信公眾號上,歡迎關注,歡迎提意見:
作者:對角另一面