This is the 18th day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021

When you update data in your code, you want to wait until the corresponding Dom is updated before executing some logic. At that point, we’re going to use $nextTick

Funcion callback(){// Wait for Dom updates and then do something. } $nextTick (the callback);Copy the code

The official documentation explains nextTick:

A deferred callback is performed after the next DOM update loop ends. Use this method immediately after modifying the data to get the updated DOM.

So how does Vue do this, does it call our callback function after calling the Api (appendChild, textContent = “XXXXX” etc.) to modify the Dom? So what actually happened.

The source code

The nextTick implementation logic is in this file:

vue/src/core/util/next-tick.js

Our call to this.$nextTick is actually this method:

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 }) } }Copy the code

You can see

  1. The callbacks are stored in an array :callbacks.
  2. If no callback is passed, the method returns a Promise, and then places reslove as a callback into flushCallbacks. So the documentation explains how to put callbacks in THEN that are supposed to be callbacks.
  3. Then, there is a variable called pending, and if it is not pending, the function timerFunc is executed. And pending defaults to false.
  4. The flushCallbacks function executes all callbacks at once.

timerFunc

TimerFunc is defined here

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

Utilizes the js event loop microtask mechanism

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

if (typeof Promise ! == 'undefined' && isNative(Promise)) { const p = Promise.resolve() timerFunc = () => { p.then(flushCallbacks) } }Copy the code

flushCallbacks

There is also a function in this file called flushCallbacks that flushes all saved callback functions.

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

pending

When is pending true?

Pending is true for the time between timerFunc being called and flushCallbacks being called

An event cycle

Callbacks added during pending will be executed by the flushCallbacks function that is already waiting for execution.

The core mechanism

Read the source code, found that in addition to the use of a micro-task mechanism, and Dom update has nothing to do with wow.

It’s not just developers who call nextTick. Vue also uses nextTick when it updates the Dom.

As soon as the developer updates the bound data, Vue calls nextTick and inserts the Dom update callback into the event loop as a microtask.

Therefore, in the microtask queue, the nextTick callback that the developer calls must be executed after the Dom callback.

But here’s the problem: according to the browser’s rendering mechanism, the render thread runs after the microtask has completed. How do I get the Dom if the render thread is not running?

After Vue updates the Dom, the new Dom node already exists in the Dom tree, and the JS thread can get the new Dom. The js thread will not be interrupted unless the developer reads the Dom’s computational properties and triggers a forced restreaming render thread.

conclusion

  1. First, the timerFunc function is responsible for dropping callbacks to the end of the event loop
  2. The nextTick function is then responsible for saving the callbacks.
  3. The timerFunc function is called when the nextTick function is called
  4. Vue updates the Dom using nextTick, too, and before the developer invokes nextTick.
  5. Because of the sequencing in 4 and the queued nature of the event loop, the developer’s nextTick callback is guaranteed to come after the Dom update