Home Web Front-end JS Tutorial Detailed introduction to nextTick method in Vue

Detailed introduction to nextTick method in Vue

Jun 08, 2018 pm 05:40 PM
nexttick vue

This article mainly introduces a simple understanding of the nextTick method in Vue. Now I will share it with you and give you a reference.

nextTick in Vue involves the asynchronous update of DOM in Vue. It feels very interesting and I learned about it specially. The source code of nextTick involves a lot of knowledge, many of which I don’t quite understand. Let’s introduce nextTick based on some of my own insights.

1. Example

Let’s take an example to learn about DOM updates in Vue and the role of nextTick.

Template

<p class="app">
 <p ref="msgp">{{msg}}</p>
 <p v-if="msg1">Message got outside $nextTick: {{msg1}}</p>
 <p v-if="msg2">Message got inside $nextTick: {{msg2}}</p>
 <p v-if="msg3">Message got outside $nextTick: {{msg3}}</p>
 <button @click="changeMsg">
  Change the Message
 </button>
</p>
Copy after login

Vue instance

new Vue({
 el: &#39;.app&#39;,
 data: {
  msg: &#39;Hello Vue.&#39;,
  msg1: &#39;&#39;,
  msg2: &#39;&#39;,
  msg3: &#39;&#39;
 },
 methods: {
  changeMsg() {
   this.msg = "Hello world."
   this.msg1 = this.$refs.msgp.innerHTML
   this.$nextTick(() => {
    this.msg2 = this.$refs.msgp.innerHTML
   })
   this.msg3 = this.$refs.msgp.innerHTML
  }
 }
})
Copy after login

Before clicking

After clicking

It can be known from the figure: the content displayed by msg1 and msg3 is before the transformation, while the content displayed by msg2 is after the transformation. The fundamental reason is that DOM updates in Vue are asynchronous (detailed explanation below).

2. Application Scenarios

Let’s learn about the main application scenarios and reasons of nextTick.

DOM operations performed in the created() hook function of the Vue life cycle must be placed in the callback function of Vue.nextTick()

In fact, when the created() hook function is executed, the DOM No rendering has been performed, and DOM operations at this time are in vain, so the js code for DOM operations must be put into the callback function of Vue.nextTick(). Corresponding to this is the mounted() hook function, because all DOM mounting and rendering have been completed when this hook function is executed, there will be no problem in performing any DOM operations in this hook function.

When there is an operation to be performed after the data changes, and this operation requires the use of a DOM structure that changes as the data changes, this operation should be put into the callback function of Vue.nextTick().

The specific reasons are explained in detail in Vue’s official documentation:

Vue performs DOM updates asynchronously. As soon as data changes are observed, Vue will open a queue and buffer all data changes that occur in the same event loop. If the same watcher is triggered multiple times, it will only be pushed into the queue once. This deduplication during buffering is important to avoid unnecessary calculations and DOM operations. Then, on the next event loop "tick", Vue flushes the queue and performs the actual (deduplicated) work. Vue internally tries to use native Promise.then and MessageChannel for asynchronous queues. If the execution environment does not support it, setTimeout(fn, 0) will be used instead.

For example, when you set vm.someData = 'new value', the component will not re-render immediately. When the queue is flushed, the component is updated on the next "tick" when the event loop queue is cleared. Most of the time we don't need to worry about this process, but if you want to do something after the DOM state is updated, it can be a bit tricky. While Vue.js generally encourages developers to think in a "data-driven" way and avoid touching the DOM directly, there are times when we really need to do that. To wait for Vue to finish updating the DOM after the data changes, you can use Vue.nextTick(callback) immediately after the data changes. This callback function will be called after the DOM update is completed.

3. NextTick source code analysis

Function

Vue.nextTick is used to delay the execution of a piece of code, it accepts 2 parameters (callback function and the context in which the callback function is executed). If no callback function is provided, a promise object will be returned.

Source code

/**
 * Defer a task to execute it asynchronously.
 */
export const nextTick = (function () {
 const callbacks = []
 let pending = false
 let timerFunc

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

 // the nextTick behavior leverages the microtask queue, which can be accessed
 // via either native Promise.then or MutationObserver.
 // MutationObserver has wider support, however it is seriously bugged in
 // UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It
 // completely stops working after triggering a few times... so, if native
 // Promise is available, we will use it:
 /* istanbul ignore if */
 if (typeof Promise !== &#39;undefined&#39; && isNative(Promise)) {
  var p = Promise.resolve()
  var logError = err => { console.error(err) }
  timerFunc = () => {
   p.then(nextTickHandler).catch(logError)
   // in problematic UIWebViews, Promise.then doesn&#39;t completely break, but
   // it can get stuck in a weird state where callbacks are pushed into the
   // microtask queue but the queue isn&#39;t being flushed, until the browser
   // needs to do some other work, e.g. handle a timer. Therefore we can
   // "force" the microtask queue to be flushed by adding an empty timer.
   if (isIOS) setTimeout(noop)
  }
 } else if (!isIE && typeof MutationObserver !== &#39;undefined&#39; && (
  isNative(MutationObserver) ||
  // PhantomJS and iOS 7.x
  MutationObserver.toString() === &#39;[object MutationObserverConstructor]&#39;
 )) {
  // use MutationObserver where native Promise is not available,
  // e.g. PhantomJS, iOS7, Android 4.4
  var counter = 1
  var observer = new MutationObserver(nextTickHandler)
  var textNode = document.createTextNode(String(counter))
  observer.observe(textNode, {
   characterData: true
  })
  timerFunc = () => {
   counter = (counter + 1) % 2
   textNode.data = String(counter)
  }
 } else {
  // fallback to setTimeout
  /* istanbul ignore next */
  timerFunc = () => {
   setTimeout(nextTickHandler, 0)
  }
 }

 return function queueNextTick (cb?: Function, ctx?: Object) {
  let _resolve
  callbacks.push(() => {
   if (cb) {
    try {
     cb.call(ctx)
    } catch (e) {
     handleError(e, ctx, &#39;nextTick&#39;)
    }
   } else if (_resolve) {
    _resolve(ctx)
   }
  })
  if (!pending) {
   pending = true
   timerFunc()
  }
  if (!cb && typeof Promise !== &#39;undefined&#39;) {
   return new Promise((resolve, reject) => {
    _resolve = resolve
   })
  }
 }
})()
Copy after login

First of all, let’s understand the three important variables defined in nextTick.

  1. callbacks: used to store all callback functions that need to be executed

  2. pending: used to mark whether the callback function is being executed

  3. timerFunc: used to trigger the execution of the callback function

Next, learn about the nextTickHandler() function.

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

This function is used to execute all callback functions stored in callbacks.

The next step is to assign the trigger method to timerFunc.

First determine whether promise is natively supported. If so, use promise to trigger the execution of the callback function;

Otherwise, if MutationObserver is supported, instantiate an observer object and observe changes in the text node. When, all callback functions are triggered to be executed.

If neither is supported, use setTimeout to set the delay to 0.

Finally is the queueNextTick function. Because nextTick is an immediate function, the queueNextTick function is a returned function that accepts parameters passed in by the user and is used to store callback functions in callbacks.

#The above picture is the entire execution process. The key lies in timeFunc(), which plays the role of delayed execution.

From the above introduction, we can know that there are three implementation methods of timeFunc().

  1. Promise

  2. MutationObserver

  3. setTimeout

其中Promise和setTimeout很好理解,是一个异步任务,会在同步任务以及更新DOM的异步任务之后回调具体函数。

下面着重介绍一下MutationObserver。

MutationObserver是HTML5中的新API,是个用来监视DOM变动的接口。他能监听一个DOM对象上发生的子节点删除、属性修改、文本内容修改等等。

调用过程很简单,但是有点不太寻常:你需要先给他绑回调:

var mo = new MutationObserver(callback)
Copy after login

通过给MutationObserver的构造函数传入一个回调,能得到一个MutationObserver实例,这个回调就会在MutationObserver实例监听到变动时触发。

这个时候你只是给MutationObserver实例绑定好了回调,他具体监听哪个DOM、监听节点删除还是监听属性修改,还没有设置。而调用他的observer方法就可以完成这一步:

var domTarget = 你想要监听的dom节点
mo.observe(domTarget, {
   characterData: true //说明监听文本内容的修改。
})
Copy after login

在nextTick中 MutationObserver的作用就如上图所示。在监听到DOM更新后,调用回调函数。

其实使用 MutationObserver的原因就是 nextTick想要一个异步API,用来在当前的同步代码执行完毕后,执行我想执行的异步回调,包括Promise和 setTimeout都是基于这个原因。其中深入还涉及到microtask等内容,暂时不理解,就不深入介绍了。

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

如何实现vue2.0响应式(详细教程)

详细讲解React中的refs(详细教程)

通过JS如何实现文字间歇循环滚动效果

The above is the detailed content of Detailed introduction to nextTick method in Vue. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How to use bootstrap in vue How to use bootstrap in vue Apr 07, 2025 pm 11:33 PM

Using Bootstrap in Vue.js is divided into five steps: Install Bootstrap. Import Bootstrap in main.js. Use the Bootstrap component directly in the template. Optional: Custom style. Optional: Use plug-ins.

How to add functions to buttons for vue How to add functions to buttons for vue Apr 08, 2025 am 08:51 AM

You can add a function to the Vue button by binding the button in the HTML template to a method. Define the method and write function logic in the Vue instance.

How to use watch in vue How to use watch in vue Apr 07, 2025 pm 11:36 PM

The watch option in Vue.js allows developers to listen for changes in specific data. When the data changes, watch triggers a callback function to perform update views or other tasks. Its configuration options include immediate, which specifies whether to execute a callback immediately, and deep, which specifies whether to recursively listen to changes to objects or arrays.

What does vue multi-page development mean? What does vue multi-page development mean? Apr 07, 2025 pm 11:57 PM

Vue multi-page development is a way to build applications using the Vue.js framework, where the application is divided into separate pages: Code Maintenance: Splitting the application into multiple pages can make the code easier to manage and maintain. Modularity: Each page can be used as a separate module for easy reuse and replacement. Simple routing: Navigation between pages can be managed through simple routing configuration. SEO Optimization: Each page has its own URL, which helps SEO.

How to reference js file with vue.js How to reference js file with vue.js Apr 07, 2025 pm 11:27 PM

There are three ways to refer to JS files in Vue.js: directly specify the path using the &lt;script&gt; tag;; dynamic import using the mounted() lifecycle hook; and importing through the Vuex state management library.

How to return to previous page by vue How to return to previous page by vue Apr 07, 2025 pm 11:30 PM

Vue.js has four methods to return to the previous page: $router.go(-1)$router.back() uses &lt;router-link to=&quot;/&quot; component window.history.back(), and the method selection depends on the scene.

How to use vue traversal How to use vue traversal Apr 07, 2025 pm 11:48 PM

There are three common methods for Vue.js to traverse arrays and objects: the v-for directive is used to traverse each element and render templates; the v-bind directive can be used with v-for to dynamically set attribute values ​​for each element; and the .map method can convert array elements into new arrays.

How to jump to the div of vue How to jump to the div of vue Apr 08, 2025 am 09:18 AM

There are two ways to jump div elements in Vue: use Vue Router and add router-link component. Add the @click event listener and call this.$router.push() method to jump.

See all articles