🌲 🌲 🌲preface

Although nextTick is not often used in business development, it is often used in interview questions. So what kind of knowledge can nextTick test, let’s analyze together. “If it is helpful to you, the thumbs-up is the biggest encouragement to me, if you understand the wrong place, hope big guy pointed out, very appreciated. ❤️”

🌴 🌴 🌴matting

Before we look at nextTick, let’s cover a little bit of ground.

🧩 🧩 🧩Asynchronous update

Vue responsive updates do not change the Dom immediately after the data changes, but update according to a certain policy

Because Vue updates the Dom asynchronously, when we modify the data, the content of the Dom node does not change immediately. When we retrieve the new content of the Dom node in this way, we still retrieve the old content. Tipes: Why does Vue update the Dom asynchronously? Optimize performance by avoiding unnecessary calculations and DOM manipulation.

“Certain strategies: Vue updates the DOM asynchronously. As long as it listens for data changes, Vue opens a queue and buffers all data changes that occur in the same event loop. If the same Watcher is triggered more than once, it is pushed to the queue only once. This removal of duplicate data while buffering is important to avoid unnecessary computations and DOM manipulation.”

const text = ref(null);
let a = ref('0');
const testFun = async () => {
  a.value = '111111';
  console.log(text.value.innerHTML, 'beforeNextTick');
  await nextTick();
  console.log(text.value.innerHTML, 'afterNextTick');
};
Copy the code

Console output:



NextTick’s callback must be executed immediately after the DOM element update task. Which brings us to the next part:Event Loop

⚙ ️ ⚙ ️ ⚙ ️Event loop

To understand how nextTick works, you need to know something about event loops. After all, there are too many Event loops to talk about, and also involve the different Event loops in Node. Nuggets have been written by many big guys, so here is a summary of my own graph.

Then, an important word about the order of execution of various tasks in the event loop:

  1. The entire script is initially executed as the first macro task
  2. During the execution, the synchronized code is executed directly, the macro task enters the macro task queue, and the micro task enters the micro task queue
  3. When the current macro task is finished, check the microtask queue. If there are any microtask queues, execute them in sequence until the microtask queue is empty
  4. Performs rendering of the browser UI thread
  5. Check whether there are Web worker tasks and execute them
  6. Execute the new macro task at the head of the queue, return to 2, and repeat until both the macro and microtask queues are empty

If you want the nextTick callback function to be executed immediately after the DOM element update task, then you need to append the nextTick callback function after the DOM update task.

🗂 🗂 🗂in-depth

NextTick: SRC /core/util/next-tick.js nextTick: SRC /core/util/next-tick.js nextTick: SRC /core/util/next-tick.js

  • Environmental compatibility
  • Different ways to execute callback queues

Tipes: Change github to Github1s when viewing the source code on Github

// Environment compatible
// Priority microtask detection
if (typeof Promise! = ='undefined' && isNative(Promise)) {
  // Check whether the browser natively supports Promises
  const p = Promise.resolve()
  timerFunc = () = > {
    p.then(flushCallbacks)
    if (isIOS) setTimeout(noop)
  }
  isUsingMicroTask = true
  // Check a variable that is not declared based on typeOf
} else if(! isIE &&typeofMutationObserver ! = ='undefined' && (isNative(MutationObserver) ||
  MutationObserver.toString() === '[object MutationObserverConstructor]'
)) {
  // Check whether the native MutationObserver is supported
  // MutationObserver: an HTML5 API that monitors DOM changes
  // It can listen for child node deletions, property changes, text changes, etc., on a DOM object
  // The callback is executed in the microtask queue
  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 (typeofsetImmediate ! = ='undefined' && isNative(setImmediate)) {
// Check whether native setImmediate is supported
  timerFunc = () = > {
    setImmediate(flushCallbacks)
  }
} else {
// Finally use setTimeout
  timerFunc = () = > {
    setTimeout(flushCallbacks, 0)}}Copy the code

Tipes: Why microtasks are preferred: In the order of execution of the event loop above, the next macro task is executed before a UI render, which is much longer than the microtask. So prioritize microtasks when they are available, and use macrotasks when they are not, gracefully downgrading.

const callbacks = []
let pending = false
// Iterate over the callback function
function flushCallbacks () {
  pending = false
  // Handle nested nextTick operations within nextTick
  const copies = callbacks.slice(0)
  callbacks.length = 0
  for (let i = 0; i < copies.length; i++) { copies[i]() } } ... Environment compatible...export function nextTick (cb? :Function, ctx? :Object) {
  let _resolve
  // When the function is executed, the incoming callback function is pushed to the callback queue
  callbacks.push(() = > {
    if (cb) {
      try {
        cb.call(ctx)
      } catch (e) {
        handleError(e, ctx, 'nextTick')}}else if (_resolve) {
      _resolve(ctx)
    }
  })
  TimerFunc is not executed in this loop
  if(! pending) { pending =true
    // Iterate over the execution
    timerFunc()
  }
  // Handle the case where the callback function is not returned
  if(! cb &&typeof Promise! = ='undefined') {
    return new Promise(resolve= > {
      _resolve = resolve
    })
  }
}
Copy the code

Tipes: nextTick can only retrieve dom changes that are executed before it, and not if you modify them again after nextTick.

📖 📖 📖 summary

The nextTick principle is a “shot in the dark, of course” question:

1. Vue Dom asynchronous update strategy 2. Knowledge related to event loop

Compared to other Vue apis, nextTick’s principle is relatively simple, and the source code is relatively small, so take a look at it, haha. “Remember to help me praise oh” finally, I wish you study progress, successful career! 🎆 🎆 🎆

Tipes: In the interview, the interviewer asked me the basic Js, # vue3 series use Teleport to wrap a popbox component # vue3 series use Proxy instead of Object.defineProperty

🔗 🔗 🔗 links

2. NextTick source code