大家好, 用最通俗易懂的话讲最难的知识点是我的座右铭,基础是进阶的前提是我的初心。
我们常常有这样的一个场景,改变了一个值之后,我们需要获取到最新的DOM信息,去做一些操作,比如
我们可以看到,第一次输出DOM信息的时候并不是最新的,但是在nextTick
中输出的DOM信息是最新的。
那我们可以看出nextTick
的作用是:当响应式数据更改后,能在回调中拿到最新的DOM信息。
在这之前我们先想一个问题,比如你更新了10次数据,难道就会更新DOM 10次吗?
for(let i = 0; i < 10; i++) {
this.num = i // 10次
}
答案是不会的,因为更新太频繁太影响性能了,那么Vue是怎么做这里的优化的呢?
其实就一个思想:将多次更新的事件合在一个数组中,然后一次性去进行更新,这样大大减少了更新频繁的问题。
那是怎么实现的呢?其实是利用异步更新,我举个简单的例子哈:
注意:例子比较简单,实际源码不是这么简单,只是为了好理解~
const queue = []
for(let i = 0; i < 10; i++) {
this.num = i
// 相当于改变num所触发的更新事件
queue.push(() => console.log(i))
}
// 微任务,异步执行
const nextTick = (cb) => {
Promise.resolve().then(() => {
queue.forEach(event => event())
// 更新完后的回调
cb()
})
}
// 宏任务,也是异步执行
const nextTick = (cb) => {
setTimeout(() => {
queue.forEach(event => event())
// 更新完后的回调
cb()
})
}
相信很多面试官问你nextTick是什么类型的任务?很多人都会回答微任务,因为大部分觉得nextTick === then
但其实这是不然的,正确的说法应该是nextTick优先是微任务,咱们可以来看看nextTick
的部分源码,就知道了:
其实nexTick
只是优先选择微任务而已,如果当前运行环境不支持微任务的话,还是会选择宏任务的~~
我的理解是:首先,代码的正常运行是一个宏任务,如果nextTick是一个宏任务的话,那么刚刚的queue.forEach(event => event())
就会在下一个宏任务中去执行,但是你并不知道在nextTick之前还产生了多少宏任务,可能产生了10个,那整个执行的流程就是这样:
queue.forEach(event => event())
所以nextTick如果是宏任务,那么不定因素很多,可能会隔很久才去执行
那如果是微任务呢?我们知道,微任务会在本次宏任务末尾去执行,所以即使在nextTick之前已经产生了10个宏任务,也不会影响nextTick的执行时机
queue.forEach(event => event())
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8