A preface.

Always want to write something in nuggets, but always afraid of writing well, so it is written in a private warehouse, self-admiration. I woke up this morning and spent one or two hours to write this article, which is a start (I dare not write it for a long time, because I saw many loopholes or problems, I did not dare to post again and begged for mercy). I will try my best to write more articles in the future, just do it.

Use two.

The vUE website says so. address

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. This method can be executed by placing a callback function in the task of the event loop.

  1. Will follow the current environmentPromise>MutationObserver>setImmediate>setTimeoutTo find the supported tasks, you can see the priority of using microtasksPromiseIf it is not supported, it will be demoted all the way to macro taskssetTimeout
  2. Because even in the fastestPromiseIn this microtask, the current synchronization task (it is understandable that the code currently executing is a synchronization task, even if it is a macro task) has completed, and the DOM is updated.
  3. So it can be used either to wait for dom updates to complete or for the current synchronized code to complete.
  4. Waiting for the DOM update to complete, for example, to get the width and height of the DOM after modifying the data (at which point the DOM may be modified), you need to pay attention to the order of modifying the data and nextTick, as explained below

3. Writing

The vUE website says so. address

// Modify the data
vm.msg = 'Hello'
// DOM has not been updated yet
Vue.nextTick(function () {
  // DOM is updated
})

// Use as a Promise (new since 2.1.0, see hints below)
Vue.nextTick().then(function () {
  // DOM is updated
})
Copy the code

At first I didn’t understand why there was a Promise, until I saw it written like this and I understood the whole code, right

export default {
  methods: {
    updateMessage: async function () {
      this.message = 'Updated'
      console.log(this.$el.textContent) // => 'not updated'
      await this.$nextTick()
      console.log(this.$el.textContent) // => 'Updated'}},}Copy the code

Four. Source code analysis

Github 🤦🏻♀️

/ * * * *@param Cb The callback function to add *@param CTX adds the context this * when the callback function executes@returns Promise | void
 */
export function nextTick(cb? :Function, ctx? :Object) {
  let _resolve
  callbacks.push(() = > {
    if (cb) {
      cb.call(ctx)
    } else if (_resolve) {
      _resolve(ctx)
    }
  })
  if(! pending) { pending =true
    timerFunc()
  }
  if(! cb &&typeof Promise! = ='undefined') {
    return new Promise((resolve) = > {
      _resolve = resolve
    })
  }
}
Copy the code

Variables used internally

  • callbacks

    This array is used to cache the current tick added callback, meaning that all callbacks added in the current synchronized code are stored in this array.

  • pending

    Used to indicate whether a callback is being executed, or if a callback has been added to the callback

    If pending is true, it indicates that the callback queue is executing. In this case, only the current callback is put into the callback queue, and no new callback queue callbacks are executed

  • timerFunc

    This is one of the four task functions performed by the callback (Promise>MutationObserver>setImmediate>setTimeout), Think of it as promise.prototype. then, and it will pull out all the callbacks that are saved in the callbacks, execute them, and empty the callbacks

    When a callback is added with nextTick when no previous callback queue is executing.

Five. Use

In the Vue source code, it is used in three places

Vue.nextTick

Vue.nextTick = nextTick
Copy the code

$nextTick

Vue.prototype.$nextTick = function (fn: Function) {
  return nextTick(fn, this)}Copy the code

nextTick(flushSchedulerQueue)

This is the callback executed in queueWatcher, and this is the point in the data binding that is not discussed here, which is the callback that is triggered when vue instance data is updated.

export default {
  methods: {
    updateMessage: async function () {
      this.$nextTick(() = > {
        console.log(this.$el.textContent) // => 'not updated'
      })
      this.message = 'Updated'
      this.$nextTick(() = > {
        console.log(this.$el.textContent) // => 'Updated'})},}},Copy the code

So pay attention to where this.$nextTick is written

After six.

Do not write point what, hurriedly point release……