Vue3 Next

Posted on  by admin

定义: 在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM. 下次 DOM 更新循环结束之后? vue 更新DOM是有策略的,不是同步更新. nextTick 可以接收一个函数做为入参. nextTick 后能拿到最新的数据. 那么 nextTick 是怎么做到的呢?为了后面的内容更好理解,这里我们得从 js 的执行机制说起.

我们都知道 JS 是单线程语言,即指某一时间内只能干一件事,有的同学可能会问,为什么 JS 不能是多线程呢?多线程就能同一时间内干多件事情了. 是否多线程这个取决于语言的用途,一个很简单的例子,如果同一时间,一个添加了 DOM,一个删除了 DOM, 这个时候语言就不知道是该添还是该删了,所以从应用场景来看 JS 只能是单线程.

# 总结

同步 在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务.

异步 不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行.

(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。.

(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。.

看到这里,有的同学可能又会问,前面我们猜想的 DOM 更新也是异步任务,那他们的这个执行顺序如何保证呢?.

queueJob 维护job列队,有去重逻辑,保证任务的唯一性,每次调用去执行 queueFlushqueuePostFlushCb 维护cb列队,被调用的时候去重,每次调用去执行 queueFlush. 开启异步任务(nextTick)处理 flushJobs.

# nextTick

处理列队,先对列队进行排序,执行queue中的job,处理完后再处理postFlushCbs, 如果队列没有被清空会递归调用flushJobs清空队列.

好了,实现全在上面了,好像还没有解开我们的疑问,我们需要搞清楚 queueJob 及 queuePostFlushCb 是怎么被调用的. 看到这里有没有恍然大悟的感觉?原来当响应式对象发生改变后,执行 effect 如果有 scheduler 这个参数,会执行这个 scheduler 函数,并且把 effect 当做参数传入.