今天你清楚vue2的nextTick的原理了吗

Posted 一腔诗意醉了酒

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了今天你清楚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被调用且回调函数处于非pending时,调用TimerFuc

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. func是一个微任务或者宏任务的函数,里面放着flushCallbacks清空当前回调队列的任务
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里面的copies是调用2的nextTickpush进去的,也就是我们定义的回调函数

    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的原理就很清楚啦。

以上是关于今天你清楚vue2的nextTick的原理了吗的主要内容,如果未能解决你的问题,请参考以下文章

今天你清楚vue2的nextTick的原理了吗

今天你清楚vue2的nextTick的原理了吗

vue2源码-- Vue.nextTick

vue2源码-- Vue.nextTick

vue2源码-- Vue.nextTick

Vue2.0 $nextTick源码理解