成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

讀Zepto源碼之Callbacks模塊

zengdongbao / 1061人閱讀

摘要:是禁用回調(diào)函數(shù),實(shí)質(zhì)是將回調(diào)函數(shù)列表置為,同時(shí)也將和置為,調(diào)用后,等方法不再生效,這些方法的首要條件是存在。效果等同于禁用回調(diào)函數(shù)。

Callbacks 模塊并不是必備的模塊,其作用是管理回調(diào)函數(shù),為 Defferred 模塊提供支持,Defferred 模塊又為 Ajax 模塊的 promise 風(fēng)格提供支持,接下來(lái)很快就會(huì)分析到 Ajax模塊,在此之前,先看 Callbacks 模塊和 Defferred 模塊的實(shí)現(xiàn)。

讀 Zepto 源碼系列文章已經(jīng)放到了github上,歡迎star: reading-zepto

源碼版本

本文閱讀的源碼為 zepto1.2.0

整體結(jié)構(gòu)

將 Callbacks 模塊的代碼精簡(jiǎn)后,得到的結(jié)構(gòu)如下:

;(function($){
  $.Callbacks = function(options) {
    ...
    Callbacks = {
      ...
    }
    return Callbacks
  }
})(Zepto)

其實(shí)就是向 zepto 對(duì)象上,添加了一個(gè) Callbacks 函數(shù),這個(gè)是一個(gè)工廠函數(shù),調(diào)用這個(gè)函數(shù)返回的是一個(gè)對(duì)象,對(duì)象內(nèi)部包含了一系列的方法。

options 參數(shù)為一個(gè)對(duì)象,在源碼的內(nèi)部,作者已經(jīng)注釋了各個(gè)鍵值的含義。

// Option flags:
  //   - once: Callbacks fired at most one time.
  //   - memory: Remember the most recent context and arguments
  //   - stopOnFalse: Cease iterating over callback list
  //   - unique: Permit adding at most one instance of the same callback
once: 回調(diào)至多只能觸發(fā)一次
memory: 記下最近一次觸發(fā)的上下文及參數(shù)列表,再添加新回調(diào)的時(shí)候都立刻用這個(gè)上下文及參數(shù)立即執(zhí)行
stopOnFalse: 如果隊(duì)列中有回調(diào)返回 `false`,立即中止后續(xù)回調(diào)的執(zhí)行
unique: 同一個(gè)回調(diào)只能添加一次
全局變量
options = $.extend({}, options)

var memory, // Last fire value (for non-forgettable lists)
    fired,  // Flag to know if list was already fired
    firing, // Flag to know if list is currently firing
    firingStart, // First callback to fire (used internally by add and fireWith)
    firingLength, // End of the loop when firing
    firingIndex, // Index of currently firing callback (modified by remove if needed)
    list = [], // Actual callback list
    stack = !options.once && [], // Stack of fire calls for repeatable lists

options : 構(gòu)造函數(shù)的配置,默認(rèn)為空對(duì)象

list : 回調(diào)函數(shù)列表

stack : 列表可以重復(fù)觸發(fā)時(shí),用來(lái)緩存觸發(fā)過(guò)程中未執(zhí)行的任務(wù)參數(shù),如果列表只能觸發(fā)一次,stack 永遠(yuǎn)為 false

memory : 記憶模式下,會(huì)記住上一次觸發(fā)的上下文及參數(shù)

fired : 回調(diào)函數(shù)列表已經(jīng)觸發(fā)過(guò)

firing : 回調(diào)函數(shù)列表正在觸發(fā)

firingStart : 回調(diào)任務(wù)的開始位置

firingIndex : 當(dāng)前回調(diào)任務(wù)的索引

firingLength:回調(diào)任務(wù)的長(zhǎng)度

基礎(chǔ)用法

我用 jQueryZepto 的時(shí)間比較短,之前也沒(méi)有直接用過(guò) Callbacks 模塊,單純看代碼不易理解它是怎樣工作的,在分析之前,先看一下簡(jiǎn)單的 API 調(diào)用,可能會(huì)有助于理解。

var callbacks = $.Callbacks({memory: true})
var a = function(a) {
  console.log("a " + a)
}
var b = function(b) {
  console.log("b " + b)
}
var c = function(c) {
  console.log("c " + c)
}
callbacks.add(a).add(b).add(c)  // 向隊(duì)列 list 中添加了三個(gè)回調(diào)
callbacks.remove(c) // 刪除 c
callbacks.fire("fire") 
// 到這步輸出了 `a fire` `b fire` 沒(méi)有輸出 `c fire`
callbacks.lock()
callbacks.fire("fire after lock")  // 到這步?jīng)]有任何輸出
// 繼續(xù)向隊(duì)列添加回調(diào),注意 `Callbacks` 的參數(shù)為 `memory: true`
callbacks.add(function(d) {  
  console.log("after lock")
})
// 輸出 `after lock`
callbacks.disable()
callbacks.add(function(e) {
  console.log("after disable")
}) 
// 沒(méi)有任何輸出

上面的例子只是簡(jiǎn)單的調(diào)用,也有了注釋,下面開始分析 API

內(nèi)部方法 fire
fire = function(data) {
  memory = options.memory && data
  fired = true
  firingIndex = firingStart || 0
  firingStart = 0
  firingLength = list.length
  firing = true
  for ( ; list && firingIndex < firingLength ; ++firingIndex ) {
    if (list[firingIndex].apply(data[0], data[1]) === false && options.stopOnFalse) {
      memory = false
      break
    }
  }
  firing = false
  if (list) {
    if (stack) stack.length && fire(stack.shift())
    else if (memory) list.length = 0
    else Callbacks.disable()
      }
}

Callbacks 模塊只有一個(gè)內(nèi)部方法 fire ,用來(lái)觸發(fā) list 中的回調(diào)執(zhí)行,這個(gè)方法是 Callbacks 模塊的核心。

變量初始化
memory = options.memory && data
fired = true
firingIndex = firingStart || 0
firingStart = 0
firingLength = list.length
firing = true

fire 只接收一個(gè)參數(shù) data ,這個(gè)內(nèi)部方法 fire 跟我們調(diào)用 API 所接收的參數(shù)不太一樣,這個(gè) data 是一個(gè)數(shù)組,數(shù)組里面只有兩項(xiàng),第一項(xiàng)是上下文對(duì)象,第二項(xiàng)是回調(diào)函數(shù)的參數(shù)數(shù)組。

如果 options.memorytrue ,則將 data,也即上下文對(duì)象和參數(shù)保存下來(lái)。

list 是否已經(jīng)觸發(fā)過(guò)的狀態(tài) fired 設(shè)置為 true。

將當(dāng)前回調(diào)任務(wù)的索引值 firingIndex 指向回調(diào)任務(wù)的開始位置 firingStart 或者回調(diào)列表的開始位置。

將回調(diào)列表的開始位置 firingStart 設(shè)置為回調(diào)列表的開始位置。

將回調(diào)任務(wù)的長(zhǎng)度 firingLength 設(shè)置為回調(diào)列表的長(zhǎng)度。

將回調(diào)的開始狀態(tài) firing 設(shè)置為 true

執(zhí)行回調(diào)
for ( ; list && firingIndex < firingLength ; ++firingIndex ) {
  if (list[firingIndex].apply(data[0], data[1]) === false && options.stopOnFalse) {
    memory = false
    break
  }
}
firing = false

執(zhí)行回調(diào)的整體邏輯是遍歷回調(diào)列表,逐個(gè)執(zhí)行回調(diào)。

循環(huán)的條件是,列表存在,并且當(dāng)前回調(diào)任務(wù)的索引值 firingIndex 要比回調(diào)任務(wù)的長(zhǎng)度要小,這個(gè)很容易理解,當(dāng)前的索引值都超出了任務(wù)的長(zhǎng)度,就找不到任務(wù)執(zhí)行了。

list[firingIndex].apply(data[0], data[1]) 就是從回調(diào)列表中找到對(duì)應(yīng)的任務(wù),綁定上下文對(duì)象,和傳入對(duì)應(yīng)的參數(shù),執(zhí)行任務(wù)。

如果回調(diào)執(zhí)行后顯式返回 false, 并且 options.stopOnFalse 設(shè)置為 true ,則中止后續(xù)任務(wù)的執(zhí)行,并且清空 memory 的緩存。

回調(diào)任務(wù)執(zhí)行完畢后,將 firing 設(shè)置為 false,表示當(dāng)前沒(méi)有正在執(zhí)行的任務(wù)。

檢測(cè)未執(zhí)行的回調(diào)及清理工作
if (list) {
  if (stack) stack.length && fire(stack.shift())
  else if (memory) list.length = 0
  else Callbacks.disable()
}

列表任務(wù)執(zhí)行完畢后,先檢查 stack 中是否有沒(méi)有執(zhí)行的任務(wù),如果有,則將任務(wù)參數(shù)取出,調(diào)用 fire 函數(shù)執(zhí)行。后面會(huì)看到,stack 儲(chǔ)存的任務(wù)是 push 進(jìn)去的,用 shift 取出,表明任務(wù)執(zhí)行的順序是先進(jìn)先出。

memory 存在,則清空回調(diào)列表,用 list.length = 0 是清空列表的一個(gè)方法。在全局參數(shù)中,可以看到, stackfalse ,只有一種情況,就是 options.oncetrue 的時(shí)候,表示任務(wù)只能執(zhí)行一次,所以要將列表清空。而 memorytrue ,表示后面添加的任務(wù)還可以執(zhí)行,所以還必須保持 list 容器的存在,以便后續(xù)任務(wù)的添加和執(zhí)行。

其他情況直接調(diào)用 Callbacks.disable() 方法,禁用所有回調(diào)任務(wù)的添加和執(zhí)行。

.add()
add: function() {
  if (list) {
    var start = list.length,
        add = function(args) {
          $.each(args, function(_, arg){
            if (typeof arg === "function") {
              if (!options.unique || !Callbacks.has(arg)) list.push(arg)
                }
            else if (arg && arg.length && typeof arg !== "string") add(arg)
              })
        }
    add(arguments)
    if (firing) firingLength = list.length
    else if (memory) {
      firingStart = start
      fire(memory)
    }
  }
  return this
},

start 為原來(lái)回調(diào)列表的長(zhǎng)度。保存起來(lái),是為了后面修正回調(diào)任務(wù)的開始位置時(shí)用。

內(nèi)部方法add
add = function(args) {
  $.each(args, function(_, arg){
    if (typeof arg === "function") {
      if (!options.unique || !Callbacks.has(arg)) list.push(arg)
        }
    else if (arg && arg.length && typeof arg !== "string") add(arg)
      })
}

add 方法的作用是將回調(diào)函數(shù) push 進(jìn)回調(diào)列表中。參數(shù) arguments 為數(shù)組或者偽數(shù)組。

$.each 方法來(lái)遍歷 args ,得到數(shù)組項(xiàng) arg,如果 argfunction 類型,則進(jìn)行下一個(gè)判斷。

在下一個(gè)判斷中,如果 options.unique 不為 true ,即允許重復(fù)的回調(diào)函數(shù),或者原來(lái)的列表中不存在該回調(diào)函數(shù),則將回調(diào)函數(shù)存入回調(diào)列表中。

如果 arg 為數(shù)組或偽數(shù)組(通過(guò) arg.length 是否存在判斷,并且排除掉 string 的情況),再次調(diào)用 add 函數(shù)分解。

修正回調(diào)任務(wù)控制變量
add(arguments)
if (firing) firingLength = list.length
else if (memory) {
  firingStart = start
  fire(memory)
}

調(diào)用 add 方法,向列表中添加回調(diào)函數(shù)。

如果回調(diào)任務(wù)正在執(zhí)行中,則修正回調(diào)任務(wù)的長(zhǎng)度 firingLength 為當(dāng)前任務(wù)列表的長(zhǎng)度,以便后續(xù)添加的回調(diào)函數(shù)可以執(zhí)行。

否則,如果為 memory 模式,則將執(zhí)行回調(diào)任務(wù)的開始位置設(shè)置為 start ,即原來(lái)列表的最后一位的下一位,也就是新添加進(jìn)列表的第一位,然后調(diào)用 fire ,以緩存的上下文及參數(shù) memory 作為 fire 的參數(shù),立即執(zhí)行新添加的回調(diào)函數(shù)。

.remove()
remove: function() {
  if (list) {
    $.each(arguments, function(_, arg){
      var index
      while ((index = $.inArray(arg, list, index)) > -1) {
        list.splice(index, 1)
        // Handle firing indexes
        if (firing) {
          if (index <= firingLength) --firingLength
          if (index <= firingIndex) --firingIndex
            }
      }
    })
  }
  return this
},

刪除列表中指定的回調(diào)。

刪除回調(diào)函數(shù)

each 遍歷參數(shù)列表,在 each 遍歷里再有一層 while 循環(huán),循環(huán)的終止條件如下:

(index = $.inArray(arg, list, index)) > -1

$.inArray() 最終返回的是數(shù)組項(xiàng)在數(shù)組中的索引值,如果不在數(shù)組中,則返回 -1,所以這個(gè)判斷是確定回調(diào)函數(shù)存在于列表中。關(guān)于 $.inArray 的分析,見《讀zepto源碼之工具函數(shù)》。

然后調(diào)用 splice 刪除 list 中對(duì)應(yīng)索引值的數(shù)組項(xiàng),用 while 循環(huán)是確保列表中有重復(fù)的回調(diào)函數(shù)都會(huì)被刪除掉。

修正回調(diào)任務(wù)控制變量
if (firing) {
  if (index <= firingLength) --firingLength
  if (index <= firingIndex) --firingIndex
}

如果回調(diào)任務(wù)正在執(zhí)行中,因?yàn)榛卣{(diào)列表的長(zhǎng)度已經(jīng)有了變化,需要修正回調(diào)任務(wù)的控制參數(shù)。

如果 index <= firingLength ,即回調(diào)函數(shù)在當(dāng)前的回調(diào)任務(wù)中,將回調(diào)任務(wù)數(shù)減少 1

如果 index <= firingIndex ,即在正在執(zhí)行的回調(diào)函數(shù)前,將正在執(zhí)行函數(shù)的索引值減少 1 。

這樣做是防止回調(diào)函數(shù)執(zhí)行到最后時(shí),沒(méi)有找到對(duì)應(yīng)的任務(wù)執(zhí)行。

.fireWith
fireWith: function(context, args) {
  if (list && (!fired || stack)) {
    args = args || []
    args = [context, args.slice ? args.slice() : args]
    if (firing) stack.push(args)
    else fire(args)
      }
  return this
},

以指定回調(diào)函數(shù)的上下文的方式來(lái)觸發(fā)回調(diào)函數(shù)。

fireWith 接收兩個(gè)參數(shù),第一個(gè)參數(shù) context 為上下文對(duì)象,第二個(gè) args 為參數(shù)列表。

fireWith 后續(xù)執(zhí)行的條件是列表存在并且回調(diào)列表沒(méi)有執(zhí)行過(guò)或者 stack 存在(可為空數(shù)組),這個(gè)要注意,后面講 disable 方法和 lock 方法區(qū)別的時(shí)候,這是一個(gè)很重要的判斷條件。

args = args || []
args = [context, args.slice ? args.slice() : args]

先將 args 不存在時(shí),初始化為數(shù)組。

再重新組合成新的變量 args ,這個(gè)變量的第一項(xiàng)為上下文對(duì)象 context ,第二項(xiàng)為參數(shù)列表,調(diào)用 args.slice 是對(duì)數(shù)組進(jìn)行拷貝,因?yàn)?memory 會(huì)儲(chǔ)存上一次執(zhí)行的上下文對(duì)象及參數(shù),應(yīng)該是怕外部對(duì)引用的更改的影響。

if (firing) stack.push(args)
else fire(args)

如果回調(diào)正處在觸發(fā)的狀態(tài),則將上下文對(duì)象和參數(shù)先儲(chǔ)存在 stack 中,從內(nèi)部函數(shù) fire 的分析中可以得知,回調(diào)函數(shù)執(zhí)行完畢后,會(huì)從 stack 中將 args 取出,再觸發(fā) fire

否則,觸發(fā) fire,執(zhí)行回調(diào)函數(shù)列表中的回調(diào)函數(shù)。

addremove 都要判斷 firing 的狀態(tài),來(lái)修正回調(diào)任務(wù)控制變量,fire 方法也要判斷 firing ,來(lái)判斷是否需要將 args 存入 stack 中,但是 javascript 是單線程的,照理應(yīng)該不會(huì)出現(xiàn)在觸發(fā)的同時(shí) add 或者 remove 或者再調(diào)用 fire 的情況。

.fire()
fire: function() {
  return Callbacks.fireWith(this, arguments)
},

fire 方法,用得最多,但是卻非常簡(jiǎn)單,調(diào)用的是 fireWidth 方法,上下文對(duì)象是 this 。

.has()
has: function(fn) {
  return !!(list && (fn ? $.inArray(fn, list) > -1 : list.length))
},

has 有兩個(gè)作用,如果有傳參時(shí),用來(lái)查測(cè)所傳入的 fn 是否存在于回調(diào)列表中,如果沒(méi)有傳參時(shí),用來(lái)檢測(cè)回調(diào)列表中是否已經(jīng)有了回調(diào)函數(shù)。

fn ? $.inArray(fn, list) > -1 : list.length

這個(gè)三元表達(dá)式前面的是判斷指定的 fn 是否存在于回調(diào)函數(shù)列表中,后面的,如果 list.length 大于 0 ,則回調(diào)列表已經(jīng)存入了回調(diào)函數(shù)。

.empty()
empty: function() {
  firingLength = list.length = 0
  return this
},

empty 的作用是清空回調(diào)函數(shù)列表和正在執(zhí)行的任務(wù),但是 list 還存在,還可以向 list 中繼續(xù)添加回調(diào)函數(shù)。

.disable()
disable: function() {
  list = stack = memory = undefined
  return this
},

disable 是禁用回調(diào)函數(shù),實(shí)質(zhì)是將回調(diào)函數(shù)列表置為 undefined ,同時(shí)也將 stackmemory 置為 undefined ,調(diào)用 disable 后,add 、remove 、fire 、fireWith 等方法不再生效,這些方法的首要條件是 list 存在。

.disabled()
disabled: function() {
  return !list
},

回調(diào)是否已經(jīng)被禁止,其實(shí)就是檢測(cè) list 是否存在。

.lock()
lock: function() {
  stack = undefined
  if (!memory) Callbacks.disable()
  return this
},

鎖定回調(diào)列表,其實(shí)是禁止 firefireWith 的執(zhí)行。

其實(shí)是將 stack 設(shè)置為 undefinedmemory 不存在時(shí),調(diào)用的是 disable 方法,將整個(gè)列表清空。效果等同于禁用回調(diào)函數(shù)。fireadd 方法都不能再執(zhí)行。

.lock() 和 .disable() 的區(qū)別

為什么 memory 存在時(shí),stackundefined 就可以將列表的 firefireWith 禁用掉呢?在上文的 fireWith 中,我特別提到了 !fired || stack 這個(gè)判斷條件。在 stackundefined 時(shí),fireWith 的執(zhí)行條件看 fired 這個(gè)條件。如果回調(diào)列表已經(jīng)執(zhí)行過(guò), firedtruefireWith 不會(huì)再執(zhí)行。如果回調(diào)列表沒(méi)有執(zhí)行過(guò),memoryundefined ,會(huì)調(diào)用 disable 方法禁用列表,fireWith 也不能執(zhí)行。

所以,disablelock 的區(qū)別主要是在 memory 模式下,回調(diào)函數(shù)觸發(fā)過(guò)后,lock 還可以調(diào)用 add 方法,向回調(diào)列表中添加回調(diào)函數(shù),添加完畢后會(huì)立刻用 memory 的上下文和參數(shù)觸發(fā)回調(diào)函數(shù)。

.locked()
locked: function() {
  return !stack
},

回調(diào)列表是否被鎖定。

其實(shí)就是檢測(cè) stack 是否存在。

.fired()
fired: function() {
  return !!fired
}

回調(diào)列表是否已經(jīng)被觸發(fā)過(guò)。

回調(diào)列表觸發(fā)一次后 fired 就會(huì)變?yōu)?true,用 !! 的目的是將 undefined 轉(zhuǎn)換為 false 返回。

系列文章

讀Zepto源碼之代碼結(jié)構(gòu)

讀 Zepto 源碼之內(nèi)部方法

讀Zepto源碼之工具函數(shù)

讀Zepto源碼之神奇的$

讀Zepto源碼之集合操作

讀Zepto源碼之集合元素查找

讀Zepto源碼之操作DOM

讀Zepto源碼之樣式操作

讀Zepto源碼之屬性操作

讀Zepto源碼之Event模塊

讀Zepto源碼之IE模塊

參考

Zepto源碼分析-callbacks模塊

讀jQuery之十九(多用途回調(diào)函數(shù)列表對(duì)象)

License

最后,所有文章都會(huì)同步發(fā)送到微信公眾號(hào)上,歡迎關(guān)注,歡迎提意見:

作者:對(duì)角另一面

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/84241.html

相關(guān)文章

  • Zepto源碼Deferred模塊

    摘要:為的項(xiàng),取出來(lái)的分別為和,所以上的和方法,調(diào)用的是中的方法,實(shí)質(zhì)是往各自的回調(diào)列表中添加回調(diào)函數(shù)。進(jìn)度回調(diào)函數(shù)數(shù)組。參數(shù)為異步對(duì)象的索引值,參數(shù)為對(duì)應(yīng)的上下文數(shù)組,即或,為對(duì)應(yīng)的回調(diào)函數(shù)數(shù)組,即或。 Deferred 模塊也不是必備的模塊,但是 ajax 模塊中,要用到 promise 風(fēng)格,必需引入 Deferred 模塊。Deferred 也用到了上一篇文章《讀Zepto源碼之C...

    yagami 評(píng)論0 收藏0
  • Zepto源碼Stack模塊

    摘要:讀源碼系列文章已經(jīng)放到了上,歡迎源碼版本本文閱讀的源碼為改寫原有的方法模塊改寫了以上這些方法,這些方法在調(diào)用的時(shí)候,會(huì)為返回的結(jié)果添加的屬性,用來(lái)保存原來(lái)的集合。方法的分析可以看讀源碼之模塊。 Stack 模塊為 Zepto 添加了 addSelf 和 end 方法。 讀 Zepto 源碼系列文章已經(jīng)放到了github上,歡迎star: reading-zepto 源碼版本 本文閱讀的...

    crossea 評(píng)論0 收藏0
  • Zepto源碼assets模塊

    摘要:模塊是為解決移動(dòng)版加載圖片過(guò)大過(guò)多時(shí)崩潰的問(wèn)題。因?yàn)闆](méi)有處理過(guò)這樣的場(chǎng)景,所以這部分的代碼解釋不會(huì)太多,為了說(shuō)明這個(gè)問(wèn)題,我翻譯了這篇文章作為附文怎樣處理移動(dòng)端對(duì)圖片資源的限制,更詳細(xì)地解釋了這個(gè)模塊的應(yīng)用場(chǎng)景。 assets 模塊是為解決 Safari 移動(dòng)版加載圖片過(guò)大過(guò)多時(shí)崩潰的問(wèn)題。因?yàn)闆](méi)有處理過(guò)這樣的場(chǎng)景,所以這部分的代碼解釋不會(huì)太多,為了說(shuō)明這個(gè)問(wèn)題,我翻譯了《How to...

    thursday 評(píng)論0 收藏0
  • Zepto源碼Gesture模塊

    摘要:模塊基于上的事件的封裝,利用屬性,封裝出系列事件。這個(gè)判斷需要引入設(shè)備偵測(cè)模塊。然后是監(jiān)測(cè)事件,根據(jù)這三個(gè)事件,可以組合出和事件。其中變量對(duì)象和模塊中的對(duì)象的作用差不多,可以先看看讀源碼之模塊對(duì)模塊的分析。 Gesture 模塊基于 IOS 上的 Gesture 事件的封裝,利用 scale 屬性,封裝出 pinch 系列事件。 讀 Zepto 源碼系列文章已經(jīng)放到了github上,歡...

    coolpail 評(píng)論0 收藏0
  • Zepto源碼Form模塊

    摘要:模塊處理的是表單提交。表單提交包含兩部分,一部分是格式化表單數(shù)據(jù),另一部分是觸發(fā)事件,提交表單。最終返回的結(jié)果是一個(gè)數(shù)組,每個(gè)數(shù)組項(xiàng)為包含和屬性的對(duì)象。否則手動(dòng)綁定事件,如果沒(méi)有阻止瀏覽器的默認(rèn)事件,則在第一個(gè)表單上觸發(fā),提交表單。 Form 模塊處理的是表單提交。表單提交包含兩部分,一部分是格式化表單數(shù)據(jù),另一部分是觸發(fā) submit 事件,提交表單。 讀 Zepto 源碼系列文章已...

    陳江龍 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<