Vue-nextTick函数到底是什么时候执行

109 阅读3分钟

看了网上很多解释,还是没看明白nextTick到底什么时候执行,DOM更新后执行又是什么意思 ?本文会用我自己的理解,跟大家说说,希望能够对大家有所帮助

看本文之前希望大家对js事件循环有所了解,不然下面可能会看不懂

首先vue的DOM更新并不是同步更新,意思就是你改变了数据vue并不会立马就更新DOM,而是异步更新DOM,那异步更新是什么意思呢

我们采用vue里面的一句话:

  • 当你在 Vue 中更改响应式状态时,最终的 DOM 更新并不是同步生效的,而是由 Vue 将它们缓存在一个队列中,直到下一个“tick”才一起执行。这样是为了确保每个组件无论发生多少状态改变,都仅执行一次更新。

就是会把所有的更新放在一个队列里面,最后只更新一次,这也是vue性能优化的一种方式

而上面说到的tick是什么呢,按我理解,就是下一次开始执行执行栈中的任务前,同理DOM的更新也是在这之前

首先我们先说说,什么是js的执行栈,什么时候开始执行,执行的是什么

这就涉及到js事件循环

js是一个单线程的语言

任务是分为同步任务异步任务,这具体我就不多说了

很多人说nextTick函数是在事件循环结束后开始执行,其实经过我的实验,它并不是这样子!!!

准确来说是在每一次执行栈里的任务执行完DOM更新后,在此次执行栈中的nextTick函数就会执行,而不是在一次事件循环后

下图是我的理解

image-20231106192252389转存失败,建议直接上传图片文件

不管是微任务被压入执行栈中还是宏任务被压入,在执行栈执行完DOM完成更新后都会执行nextTick函数

我们也可以看具体代码,分析在注释里

<script setup>
import {nextTick } from "vue";

console.log("script start");   

nextTick(() => console.log("necttick start"));   //这个nextTick是同步任务里的,同步任务被压入执行栈中并且执行完后执行这nextTick
    
new Promise((resolve) => {
  resolve();
}).then((res) => {           //把then函数压入微任务中
  nextTick(() => console.log("necttick start-then"));//这是微任务里的,微任务被压入执行栈中并且执行完后执行这nextTick
  console.log("then1");      
});
new Promise((resolve) => {
  resolve();
}).then((res) => {    //把then函数压入微任务中
  console.log("then2");
});
     
setTimeout(() => {
   nextTick(() => console.log("necttick start-宏任务"));   //这个nextTick函数是宏任务里的,宏任务被压入执行栈中并且执行完后执行这nextTick
  console.log("settimeout start");
}, 2000);

console.log("script end");
</script>

其执行结果为

script start
script end
necttick start    //同步任务被压入执行栈中并且执行完后执行这nextTick的结果
then1
then2
necttick start-then //微任务被压入执行栈中并且执行完后执行这nextTick的结果
settimeout start
necttick start-宏任务  //宏任务被压入执行栈中并且执行完后执行这nextTick的结果

nextTick() 可以在状态改变后立即使用,以等待 DOM 更新完成。你可以传递一个回调函数作为参数,或者 await 返回的 Promise。

不难看出,nextTick会在本次执行栈执行完后再执行

所以nextTick执行的时机就会很清晰