This is the 14th day of my participation in the August Text Challenge.More challenges in August

This article covers the nextTick API concept, usage, and source code. Systematically review the usage of nextTick and the internal invocation logic.

concept

Official explanation: 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.

In plain English: nextTick is a batch asynchronous update policy in VUE. When a component change is heard, it is not updated immediately, and a queue is opened, and the same Watcher is enqueued only once. On the next event loop, the refresh queue performs the update.

The principle of

Use nextTick to receive the incoming callback, temporarily place the callback in a queue, and enable asynchronous updates (calling the timerfuc function). The Promise microtask is used in preference in timerfuc to perform all callbacks in the queue, updating the page on the next event loop.

There is also a downgrading process in Timerfuc that takes into account browser compatibility Settings. Degrade order: Promise => MutationObserver => setImmediate => setTimeout

You can see that nextTick actually leverages the browser’s event loop mechanism. Tasks in nextTick are placed in a microtask queue (if the browser is microtask compatible). When the function execution stack is empty, it checks whether there are microtasks in the microtask queue. If there are, the tasks in the microtask queue (which can execute tasks in nextTick) will be executed first, and then the macro task will be executed.

Details on how JS works can be found hereJS runtime mechanismThis article.

How to work

use

NextTick receives two incoming objects, a callback from the user and a context object. Within the component, this is automatically bound to the current Vue instance when the user uses it, so there is no need for the global Vue to call vue.nexttick (cb).

  <div id="app">
    <h1>Asynchronous update</h1>
    <p id="p1">{{count}}</p>
  </div>
  <script>
    const vm = new Vue({
      el: '#app'.data: {
        count: Original value
      },
      mounted() {
        this.count = Math.random()
        console.log('First change value :'.this.count)
        this.$nextTick(() = > {
          console.log('innerHTML', p1.innerHTML); })}})</script>
Copy the code

We can see that after the page loads, count successfully retrieves the value of the first change and is updated on the page.

Source analysis

So, how does the page render? As always, let’s take a look at what’s going on inside the source code using the console interrupt point.

First of all, from thethis.countBecause the variable is retrieved through this, instead of using $data inside this, it goes to the variable’s proxyproxyMiddle, and then it entersdefineRectiveSet interception in.In set interception, go back and tell DEP to do the update.

Execute Watcher’s update function update in notify. Before doing this, we can see that there is a sort of Watcher, the source code will create the higher level watcher first, execute first.

Update by iterating, attempting to enqueue the incoming Watcher instance and start the asynchronous task.

Add one to nextTickflushSchedulerQueueThe callback. And put it incallbacksIn the array. Starting an Asynchronous Tasktimerfuc:

In an asynchronous task, executeflushCallbacks.

Inside it is the traversal executioncallbacksThe array is just like the one before the executionflushSchedulerQueueThe callback.

And in theflushSchedulerQueueThe callback iterates over all watchers and executes their run function.In watcher’s run function, it performs its own GET. It really goes to component updatesupdateComponent. inupdateComponentInternally, render() is performed to get the virtual DOM, _update() is performed to receive the VNode, and patch (oldvNode, vnode) is performed to change the real DOM.

You can read it by looking at this nextTick flow chart and working with the console flow chart.

application

1. Obtain the latest value after DOM update. According to the example in this article, when we want to obtain the latest count value after dom update after modifying count n times:

mounted() {
  this.count = Math.random()
  console.log('First change value :'.this.count)
  this.count = Math.random()
  console.log('Second change value :'.this.count)
  this.count = Math.random()
  console.log('Third change value :'.this.count)
  this.$nextTick(() = > {
    console.log('innerHTML', p1.innerHTML); })},Copy the code

Pay attention to the point

  • When I willnextTickWhen you put it to the front, you don’t get the latest value, you get the original value.

This is because innextTick, the desired variable has not yet entered the queue for asynchronous updates. In the asynchronous update queuenextTickIt goes in first, and then the relevant variables go into the queue, sonextTickThe output will be the original value.

  • It does not change after the first or second change.

That’s because watcher only made the team once. The first time you change the value, the count variable goes into the asynchronous update queue, and thennextTickBefore entering. Depending on the nature of the queue, the count variable is modified before it is executednextTick. So you can still get the latest value of count.

  • If I had a variable change,nextTickWill precedePromiseThe execution.
mounted() {
  this.count = Math.random()
  console.log('First change value :'.this.count)
  Promise.resolve().then((res) = > {
    console.log('Promise', p1.innerHTML);
  })
  this.$nextTick(() = > {
    console.log('innerHTML', p1.innerHTML);
  })
  this.count = Math.random()
  console.log('Second change value :'.this.count)
  this.count = Math.random()
  console.log('Third change value :'.this.count)
},
Copy the code

When a value is changed, an asynchronous update queue is triggered, and the variable is placed in the queue before executionPromiseAnd put it in an asynchronous queue.

2. Click to get the width and height of the element, scroll position, etc

One item for those interested can be plus-one item for Vue beginner’s edition or follow me for a follow-up item (●’◡’●). If not, please give me your advice.