This is the 11th day of my participation in the August More Text Challenge. For details, see:August is more challenging

The understanding of Vue.nextTick is not in place all the time, and I also have some doubts. Until I read several articles, I have some clarity, and summarize its principle and use. If you have a different understanding during the review, please discuss it.

Vue. NextTick knowledge

NextTick ([callback,context]); Parameter description:

  1. {Function} [callback] : provide promise calls when not passed;Copy the code
  2. {Object} [context] : The context in which the callback function is executed. By default, it is automatically bound to the calling instance;Copy the code
// Modify the data
vm.msg = 'Hello'
// DOM hasn't been updated yet
Vue.nextTick(function () {
  // The DOM is updated./ / DOM manipulation
})

// Use as a Promise
Vue.nextTick()
  .then(function () {
    // The DOM is updated
  })
Copy the code

Vue. NextTick


Vue executes asynchronously when updating the DOM. As soon as data changes are listened for, Vue opens a queue and buffers all data changes that occur in the same event loop. If the same watcher is fired multiple times, it will only be pushed into the queue once. This removal of duplicate data at buffering time is important to avoid unnecessary computation and DOM manipulation. Then, in the next event loop “tick”, Vue refreshes the queue and performs the actual (deduplicated) work. Vue internally tries to use native Promise. Then, MutationObserver, and setImmediate for asynchronous queues, and if the execution environment does not support it, setTimeout(fn, 0) is used instead.

In particular, asynchronous execution works as follows.

(1) All synchronization tasks are executed on the main thread, forming an execution context stack. (2) There is a “task queue” in addition to the main thread. Whenever an asynchronous task has run results, an event is placed in the “task queue”. (3) Once all the synchronized tasks in the “execution stack” are completed, the system reads the “task queue” to see what events are in it. The corresponding asynchronous tasks then end the wait state, enter the execution stack, and start to execute. (4) The main thread repeats the third step above.

For example, when you set vm.someData = ‘new value’, the component does not immediately rerender. When the queue is flushed, the component is updated in the next event loop “tick”. Most of the time we don’t need to care about this process, but if you want to do something based on the updated DOM state, it can get a little tricky. While vue.js generally encourages developers to think “data-driven” and avoid direct contact with the DOM, sometimes it is necessary. To wait for Vue to finish updating the DOM after the data change, use vue.nexttick (callback) immediately after the data change. The callback function will then be called after the DOM update is complete.

The following is the main thread and task queue execution flowchart

Vue does not update the view immediately after the data is changed. Instead, it updates the view uniformly after all the data changes in the same event loop are completed.

Event loop:

The first tick (the first step in the legend, which is’ this update loop ‘) :

First modify the data, this is the synchronization task. All synchronous tasks of the same event loop are executed on the main thread, forming an execution stack, and DOM is not involved at this point. Vue starts an asynchronous queue and buffers all data changes that occur in this event loop. If the same watcher is fired multiple times, it will only be pushed into the queue once.

Second TICK (the second step in the legend, that is, ‘next update loop’) :

After the synchronization task is completed, tasks on the asynchronous Watcher queue are executed and the DOM is updated. Vue internally tries to use the native promise.then and MessageChannel methods for the asynchronous queue, and if the execution environment does not support them, uses setTimeout(fn, 0) instead.

Third tick (third step in the legend) :

That’s what the document says

After the next DOM update loop ends

NextTick to get the changed DOM. It can also be obtained by setTimeout(fn, 0).

Simple summary

NextTick [event loop 1] -> Find asynchronous queue, push to execution stack, execute Vue.nextTick[event loop 2]…

In short, asynchrony is a single tick and does not occur in the same tick as synchronization, which is why the DOM does not change immediately.

This section describes how to use nextTick

  • 1. DOM operations performed by the created() hook function in the Vue lifecycle must be placed in the callback function of vue.nextTick ().
  • 2. When the created() hook function is executed, the DOM does not render anything, and it is useless to operate the DOM at this time, so here must put the DOM operation JS code into the callback function of vue.nexttick (). The equivalent is the Mounted () hook function, which executes with all the DOM mounted and rendered, and no DOM manipulation can be done in the hook function.
  • 3. Any operation to be performed after the data changes that requires DOM structures that change with the data should be included in the vue.nexttick () callback.
  • For example, when you set vm.someData = ‘new value’, the component does not immediately rerender. When refreshing the queue, the component gets the next “tick” update when the event loop queue is empty. Most of the time we don’t need to care about this process, but if you want to do something after DOM status updates, it can get a little tricky. While vue.js generally encourages developers to think “data-driven” and avoid direct contact with the DOM, sometimes we do. To wait for Vue to finish updating the DOM after the data change, use vue.nexttick (callback) immediately after the data change. The callback function is then called after the DOM update is complete.

You need to act on the new view after it has been updated.

Created, mounted

Note that the nextTick method is also used during the Created and Mounted phases if you want to manipulate the rendered view.

Official document description:

Note that Mounted does not promise that all child components will be mounted together. If you want to wait until the entire view is rendered, replace Mounted with vm.$nextTick

 mounted: function () {
  this.$nextTick(function () {
    // Code that will run only after the
    // entire view has been rendered})}Copy the code

Scenario 1: If you want to manipulate the DOM in the created hook function, you need to execute it in the wue.nextTick () callback;

<template>
  <div>
    <h3 ref="title">Hello World!</h3>
  </div>
</template>

<script>
  export default {
    created() {
      console.log('created');
      console.log(this.$refs.title)
      this.$nextTick(() = > {
        console.log('created-nextTick');
        console.log(this.$refs.title)
      })
    },
    mounted() {
      console.log('mounted');
      console.log(this.$refs.title)
      this.$nextTick(() = > {
        console.log('mounted-nextTick');
        console.log(this.$refs.title)
      })
    }
  }
</script>
Copy the code

Based on the order of the output values, you can see that the DOM is not rendered when the created() hook function is executed. At this point, manipulating the DOM has no effect, whereas the DOM object can be obtained if the nextTick is used in the created. Since the Mounted () hook function has already mounted and rendered the DOM, there is no problem manipulating the DOM at this point. Scenario 2: When the data changes and we want to get the modified DOM structure to do something, we need to put it in the Vue. NextTick () callback.

<template>
  <div>
    <h3 ref="title">{{msg}}</h3>
    <el-button @click="changeMsg">Click</el-button>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        msg: 'hello'}},methods: {
      changeMsg() {
        this.msg = 'changed';
        console.log(this.msg);               // Order 1: changed
        console.log(this.$refs.title.innerHTML)      // Order 2: hello
        this.$nextTick(() = > {
          console.log(this.$refs.title.innerHTML)     // Order 4: changed
        })
        console.log(this.$refs.title.innerHTML)       // Order 3: hello}}}</script>
Copy the code

Through the execution results, we found that the data value was modified immediately after the modification, but the corresponding DOM was not updated in time. NextTick updates DOM through certain policies. Next, let’s look at its implementation principle.

The road ahead is long; I see no ending. I will search up and down

Welcome to leave a comment ~*