vue中对nextTick理解

1. 作用

Vue中视图更新是异步的,如果想要在视图更新后操作逻辑,例如获取DOM,就需要使用该方法来操作。

2. 调用顺序?

可以先看看上图,打印的答案是多少?我直接说结果,是10。

可能我们都听说过,nextTick是个异步方法,按道理应该先同步的执行,再轮到它执行,结果应该是300吧。那这里为什么结果是10呢?这个就要从源码去分析了,继续往下看。

来看下Vue2的源码

这里的源码主要表达的意思是,我们调用nextTick的时候,vue里会用一个数组把你的回调函数存储起来先,就是图中的callbacks。接着会去执行timerFunc方法。

timerFunc这个放到后面再详细说名,现在这里先简单认为它是个Promise的方法就行

到这里我们就应该可以明白了,用户自定义在nextTick传进来的回调函数,其实是给callbacks数组存储起来先了。

然后此时我们页面代码就会执行到下面的赋值操作

这个修改响应式变量,就会让vue里面去触发watcher队列方法,可以看下图源码

(watcher主要就是改变响应式数据会去调用自身的update方法触发组件重新渲染,但它不会一收到一次数据改变就去更新,会收集多次数据一次更新)

这个方法主要是说多次改变数据,watcher需要触发更新的时候,会有个watcher队列,会阻止重复的watcher加入。需要队列的原因是因为有可能触发多个组件更新,就会有不同的watcher。对于我们开头页面的例子,因为只涉及一个组件,可以理解成 queue=[watcher]

到最后就会调用nextTick(flushSchedulerQueue),将flushSchedulerQueue当做回调函数传给nextTick去执行。flushSchedulerQueue方法就是个循环跑queue队列里面每个watcher的run方法,去触发每个组件的更新。

好了,其实上面就是想说明,响应式数据的改变会触发组件更新,在nextTick中会加入组件渲染的函数。所以回到最开始,callbacks数组现在就要变成这样的数据:callbacks = [用户自定义回调函数,组件渲染的函数]

然后等页面的同步代码data赋值走完,这个队列就会依次执行,就是上面说的Promise中的then回调执行。(右图就是callbacks队列里的方法依次执行)

所以回到最开始的问题,下图这个用户自定义回调函数是先执行的,而此时组件渲染的函数还没执行,所以页面打印出来时一开始还没变化渲染的值10。

如果此时我们调换下页面的代码顺序(下图),那打印的值就是300了。

因为此时callbacks = [组件渲染的函数,用户自定义回调函数] 。组件已经先渲染好了,才去调用户的自定义回调函数,所以打印的值就是300。

 3.nextTick任务是宏任务还是微任务?

可能有人会直接简单认为就是微任务。但其实在Vue2中并不是那么准确。(注意是Vue2中,Vue3可以这样认为)。先说结论:我们可以说优先是微任务,在不支持Promise和MutationObserver的环境下就是宏任务。

Vue2源码中为了适配,采用了优雅降低的方式,就是我们前面说的timerFunc方法,它完整的代码如下。(由于太长,我截成两个图,第一个图是Promise最优先的)

从源码可以看出来,Vue2中会有个优雅降级的适配,是否能用Promise->是否能用MutationObserver->是否能用setImmediate->最后用setTimeout兜底。

所以才会得到上面的结论:优先是微任务,在不支持Promise和MutationObserver的环境下就是宏任务。

当然也要注意在Vue3中,源码是直接使用Promise处理,不再处理兼容问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值