持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第28天,点击查看活动详情
在文章vue2关于响应式原理源码详解(4)- 派发更新中,了解了queueWatcher()方法和flushSchedulerQueue()方法,Vue默认是使用异步执行DOM更新,当异步执行update的时候,会调用queueWatcher函数。Watch对象被push进一个queue队列,等到下一个tick运行时,这些Watch对象才会被遍历取出,更新视图。那么本文则来着重了解什么是下一个tick?其实就是,vue提供了一个nextTick函数,即queueWatcher()方法调用的。
传送门:nextTick方法源码
eventloop
在进入正文之前,先简单了解一下eventloop,JS 的 event loop 执行时会区分宏任务和微任务,引擎在每个宏任务 执行完毕,从队列中取下一个宏任务来执行之前,会先执行完所有微任务队列中的微任务。
nextTick
由源码可以看到,传入的cb都会被push进callbacks中存放起来,然后执行timerFunc,其中pending是一个标志位,如果已经有timerFunc被推送到任务队列中去则不需要重复推送,保证timerFunc在下一个tick之前只执行一次
nextTick这个函数比较简单,主要作用是在宏任务或者微任务中推入一个timerFunc,在当前调用栈执行完以后以此执行直到执行到timerFunc,目的是延迟到当前调用栈执行完以后执行
timerFunc
由源码可以看到,timerFunc是会检测当前环境,按照Promise,MutationObserver,setTimeout优先级,哪个存在就用哪个。
那么为什么要使用微任务呢?
其实是这样的,根据 HTML Standard,在每个宏任务运行完以后,UI 都会重渲染,那么在微任务中就完成数据更新,当前宏任务结束就可以得到最新的 UI 了。 反之如果新建一个宏任务来做数据更新,那么渲染就会进行两次。
综上所示,可以得出以下结论:nextTick的目的就是产生一个回调函数加入宏任务或者微任务中,当前栈执行完以后调用该回调函数,起到了异步触发的目的。