讀Zepto源碼之Form模塊

Form 模塊處理的是表單提交。表單提交包含兩部分,一部分是格式化表單數據,另外一部分是觸發 submit 事件,提交表單。javascript

讀 Zepto 源碼系列文章已經放到了github上,歡迎star: reading-zeptojava

源碼版本

本文閱讀的源碼爲 zepto1.2.0node

GitBook

reading-zeptogit

.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 方法。github

serializeArray 最終返回的結果是一個數組,每一個數組項爲包含 namevalue 屬性的對象。其中 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)) 若是是 radiocheckbox 時,則必需要選中,這個也很好理解,若是沒有選中,也不會有值須要處理。

而後調用 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 序列化 namevalue 的值,並用 = 號拼接成字符串,存進新的數組中,最後調用 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 ,提交表單。

注意 eqget 的區別, eq 返回的是 Zepto 對象,而 get 返回的是 DOM 元素。

系列文章

  1. 讀Zepto源碼之代碼結構
  2. 讀Zepto源碼以內部方法
  3. 讀Zepto源碼之工具函數
  4. 讀Zepto源碼之神奇的$
  5. 讀Zepto源碼之集合操做
  6. 讀Zepto源碼之集合元素查找
  7. 讀Zepto源碼之操做DOM
  8. 讀Zepto源碼之樣式操做
  9. 讀Zepto源碼之屬性操做
  10. 讀Zepto源碼之Event模塊
  11. 讀Zepto源碼之IE模塊
  12. 讀Zepto源碼之Callbacks模塊
  13. 讀Zepto源碼之Deferred模塊
  14. 讀Zepto源碼之Ajax模塊
  15. 讀Zepto源碼之Assets模塊
  16. 讀Zepto源碼之Selector模塊
  17. 讀Zepto源碼之Touch模塊
  18. 讀Zepto源碼之Gesture模塊
  19. 讀Zepto源碼之IOS3模塊
  20. 讀Zepto源碼之Fx模塊
  21. 讀Zepto源碼之fx_methods模塊
  22. 讀Zepto源碼之Stack模塊

附文

參考

License

署名-非商業性使用-禁止演繹 4.0 國際 (CC BY-NC-ND 4.0)

最後,全部文章都會同步發送到微信公衆號上,歡迎關注,歡迎提意見:

做者:對角另外一面

相關文章
相關標籤/搜索