SoFunction
Updated on 2025-04-11

Comprehensive parsing $nextTick in Vue

When the data is updated in the code and you hope to wait until the corresponding Dom is updated, then some logic will be executed. At this time, we will use $nextTick

funcion callback(){
 //Wait for Dom to update and then do something.}
$nextTick(callback);

The official documentation explains nextTick as:

Execute a delayed callback after the next DOM update loop ends. Use this method immediately after modifying the data to obtain the updated DOM.

So, how does Vue do this, is it called our callback function after calling the modify Dom's API (appendChild, textContent = "xxxxx" and so on)?
What actually happened.

Source code

NextTick's implementation logic is in this file:

vue/src/core/util/

The this.$nextTick we call is actually this method:

export function nextTick (cb?: Function, ctx?: Object) {
 let _resolve
 (() => {
  if (cb) {
   try {
    (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
  })
 }
}

Can see

  1. The callback function is stored in an array: callbacks.
  2. If the callback function is not passed, this method will return a promise, and then reslove will be placed in flushCallbacks as the callback function. So the documentation explains the usage of putting callbacks that should be regarded as callback functions into then.
  3. Then, there is a variable called pending. If it is not in pending, the function timerFunc is executed. And pending is equal to false by default.
  4. flushCallbacks function will execute all callback functions in one breath.

timerFunc

timerFunc is defined here

You can see that timerFunc executes flushCallbacks in then in a resolved Promise.

The mechanism of micro-tasks using js event loop

So, whenever we call $nextTick, if pending is false, timerFunc will be called, and timerFunc will stuff flushCallbacks to the end of the event loop and wait for it to be called.

if (typeof Promise !== 'undefined' && isNative(Promise)) {
 const p = ()
 timerFunc = () => {
  (flushCallbacks)
 }
}

flushCallbacks

Then there is another function in this file called flushCallbacks
Used to execute all saved callback functions and clear them.

function flushCallbacks () {
 pending = false
 const copies = (0)
  = 0
 for (let i = 0; i < ; i++) {
  copies[i]()
 }
}

pending

When is pending true?

pending to true from timerFunc is called to flushCallbacks is called

That is, an event cycle

The callback function added during pending will be executed by the flushCallbacks function that has been waiting for execution.

Core mechanism

After reading the source code, I found that except for using a micro-task mechanism, it has nothing to do with Dom updates.

In fact, it is not only the developers who call nextTick, but also nextTick is used when Vue updates Dom.

After the developer updates the bound data, Vue will immediately call nextTick and plug the callback function that updates Dom into the event loop as a micro task.

Therefore, in the microtask queue, the nextTick callback function called by the developer must be executed after the Dom callback function is more.

But the problem arises again. According to the browser's rendering mechanism, the rendering thread runs after the micro task is executed. The rendering thread is not running, how can I get the Dom?

Because the rendering thread just renders the Dom tree into a UI. After Vue updates Dom, in the Dom tree, the new Dom node already exists, and the js thread can already get the new Dom. The js thread will be interrupted unless the developer reads the computed properties of Dom and triggers the forced re-streaming rendering thread.

Summarize

  1. First of all, the timerFunc function is responsible for throwing the callback functions to the end of the event loop.
  2. Then, the nextTick function is responsible for saving all the callback functions.
  3. The timerFunc function will be called when calling the nextTick function.
  4. Vue update Dom will also use nextTick, and before the developer calls nextTick.
  5. Because of the sequence relationship in 4 and the queue nature of the event loop, the developer's nextTick callback must be after Dom update

The above is the detailed content of parsing $nextTick in Vue. For more information about $nextTick in Vue, please follow my other related articles!