今日はvue2のnextTickの原理をご存知ですか?

記事ディレクトリ

1. 入口

  1. src\core\instance\index.js内部renderMixin(Vue)

  2. src\core\instance\render.js内部

export function renderMixin (Vue: Class<Component>) {
    
    
  installRenderHelpers(Vue.prototype)
  Vue.prototype.$nextTick = function (fn: Function) {
    
    
    return nextTick(fn, this)
  }
    ...
}

  1. src\core\util\next-tick.js

    export function nextTick (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()
      }
      // $flow-disable-line
      if (!cb && typeof Promise !== 'undefined') {
          
          
        return new Promise(resolve => {
          
          
          _resolve = resolve
        })
      }
    }
    
    

2.nextTick実行プロセス

  1. マイクロタスクとマクロタスクのどちらを使用するかを決定し、timerfunc
if (typeof Promise !== 'undefined' && isNative(Promise)) {
    
    
  const p = Promise.resolve()
  timerFunc = () => {
    
    
    /**
     * 启动微任务
     */
    p.then(flushCallbacks)
    if (isIOS) setTimeout(noop)
  }
  isUsingMicroTask = true
} else if (!isIE && typeof MutationObserver !== 'undefined' && (
  isNative(MutationObserver) ||
  MutationObserver.toString() === '[object MutationObserverConstructor]'
)) {
    
    
  let counter = 1
  const observer = new MutationObserver(flushCallbacks)
  const textNode = document.createTextNode(String(counter))
  observer.observe(textNode, {
    
    
    characterData: true
  })
  timerFunc = () => {
    
    
    counter = (counter + 1) % 2
    textNode.data = String(counter)
  }
  isUsingMicroTask = true
} else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {
    
    
  timerFunc = () => {
    
    
    setImmediate(flushCallbacks)
  }
} else {
    
    
  timerFunc = () => {
    
    
    setTimeout(flushCallbacks, 0)
  }
}
  1. nextTickコールバック関数が呼び出されていない場合はpendingTimerFuc

export function nextTick (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()
  }
  // $flow-disable-line
  if (!cb && typeof Promise !== 'undefined') {
    
    
    return new Promise(resolve => {
    
    
      _resolve = resolve
    })
  }
}
  1. flushCallbacksfunc は、現在のコールバック キューをクリアするタスクを含むマイクロタスクまたはマクロタスク関数です。
function flushCallbacks () {
    
    
  pending = false

  // arrayObject.slice(start,end) 返回选定元素
  const copies = callbacks.slice(0)
  callbacks.length = 0
  for (let i = 0; i < copies.length; i++) {
    
    
    copies[i]()
  }
}

注:flushCallbacks内部はcopies2 のnextTickプッシュと呼ばれ、これは私たちが定義したコールバック関数です

    if (cb) {
    
    
      try {
    
    
        cb.call(ctx)
      } catch (e) {
    
    
        handleError(e, ctx, 'nextTick')
      }
    } else if (_resolve) {
    
    
      _resolve(ctx)
    }

Vue を使用するときに nextTick を使用する方法を振り返ると明らかになります。

this.$nextTick(()=>{
    
    
	console.log('hahha')
})
()=>{
    
    
	console.log('hahha')
}

// 这个函数就是我们的copies啦

公式写真を投稿する

ここに画像の説明を挿入

  • ここでの原則はnextTick非常に明確です。

おすすめ

転載: blog.csdn.net/qq_45704048/article/details/121803840