vue nextTickソースコード解析

13264 ワード

ソース:
export const nextTick = (function () {
  const callbacks = []
  let pending = false
  let timerFunc

  function nextTickHandler () {
    pending = false
    const copies = callbacks.slice(0)
    callbacks.length = 0
    for (let i = 0; i < copies.length; i++) {
      copies[i]()
    }
  }

  if (typeof Promise !== 'undefined' && isNative(Promise)) {
    var p = Promise.resolve()
    var logError = err => { console.error(err) }
    timerFunc = () => {
      p.then(nextTickHandler).catch(logError)

      if (isIOS) setTimeout(noop)
    }
  } else if (!isIE && typeof MutationObserver !== 'undefined' && (
    isNative(MutationObserver) ||
  
    MutationObserver.toString() === '[object MutationObserverConstructor]'
  )) {

    var counter = 1
    var observer = new MutationObserver(nextTickHandler)
    var textNode = document.createTextNode(String(counter))
    observer.observe(textNode, {
      characterData: true
    })
    timerFunc = () => {
      counter = (counter + 1) % 2
      textNode.data = String(counter)
    }
  } else {

    timerFunc = () => {
      setTimeout(nextTickHandler, 0)
    }
  }

  return function queueNextTick (cb?: Function, ctx?: Object) {
    let _resolve
    callbacks.push(() => {
      if (cb) {
        try {
          cb.call(ctx)
        } catch (e) {
          handleError(e, ctx, 'nextTick')
        }
      } else if (_resolve) {
        _resolve(ctx)
      }
    })
    if (!pending) {
      pending = true
      timerFunc()
    }
    if (!cb && typeof Promise !== 'undefined') {
      return new Promise((resolve, reject) => {
        _resolve = resolve
      })
    }
  }
})()

nextTickは、コールバック関数とコールバック関数を実行するコンテキスト環境(ctx、フルネームExecution Context)の2つのパラメータを受信するコードの実行を遅延させるために使用され、コールバック関数が指定されていない場合はpromiseオブジェクトに戻ります.
なぜコードの実行を遅らせる必要があるのかについては、vue政府もVueがDOM更新を非同期で実行すると説明した.データの変化が観察される限り、Vueはキューを開き、同じイベントサイクルで発生したすべてのデータの変化をバッファリングします.同じwatcherが複数回トリガーされると、キューに1回のみプッシュされます.このようなバッファリング時に重複データを除去することは,不要な計算やDOM動作を回避する上で非常に重要である.次に、次のイベントループ「tick」で、Vueはキューをリフレッシュし、実際の(重複した)作業を実行します.
まず、3つの変数を定義します.callbacks:実行するコールバック関数を格納します.pending:コールバック関数を実行しているかどうかをマークします.timerFunc:コールバック関数の実行をトリガーします.
次のnexttickHandler関数は、timerFuncに値を割り当て、callbacksに格納されているすべてのコールバック関数を実行するために使用されます.
次に、vueは最適なスキームに従ってコールバックをトリガーします.1、promiseがサポートされているかどうか、もしそうであればpromiseを使用してコールバック関数を実行します.2、MutationObserverがサポートされているかどうか、もしそうであれば、MutationObserverを使用してコールバック関数を実行します.これはH 5に追加されたAPIで、DOMの変動を監視します.3、前の両方がサポートされていない場合は、最後の古い仲間、settimeoutで実行し、遅延を0に設定します.
最後に、ユーザが入力したコールバック関数と実行コンテキストを受信し、コールバック関数をcallbacksに格納するqueueNextTick関数を返します.(queueはキューの意味)
したがって、nextTick関数全体がqueueNextTickを先に実行し、timerFuncで遅延し、最後にnextTickHandlerで関数を実行します.