看了网上很多解释,还是没看明白nextTick到底什么时候执行,DOM更新后执行又是什么意思 ?本文会用我自己的理解,跟大家说说,希望能够对大家有所帮助
看本文之前希望大家对js的事件循环有所了解,不然下面可能会看不懂
首先vue的DOM更新并不是同步更新,意思就是你改变了数据vue并不会立马就更新DOM,而是异步更新DOM,那异步更新是什么意思呢
我们采用vue里面的一句话:
- 当你在 Vue 中更改响应式状态时,最终的 DOM 更新并不是同步生效的,而是由 Vue 将它们缓存在一个队列中,直到下一个“tick”才一起执行。这样是为了确保每个组件无论发生多少状态改变,都仅执行一次更新。
就是会把所有的更新放在一个队列里面,最后只更新一次,这也是vue性能优化的一种方式
而上面说到的tick是什么呢,按我理解,就是下一次开始执行执行栈中的任务前,同理DOM的更新也是在这之前
首先我们先说说,什么是js的执行栈,什么时候开始执行,执行的是什么
这就涉及到js的事件循环
js是一个单线程的语言
任务是分为同步任务和异步任务,这具体我就不多说了
很多人说nextTick函数是在事件循环结束后开始执行,其实经过我的实验,它并不是这样子!!!
准确来说是在每一次执行栈里的任务执行完DOM更新后,在此次执行栈中的nextTick函数就会执行,而不是在一次事件循环后
下图是我的理解

不管是微任务被压入执行栈中还是宏任务被压入,在执行栈执行完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执行的时机就会很清晰