nextTick

功能

在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM

用法

// 修改数据
vm.msg = 'Hello';
// DOM 还没有更新
Vue.nextTick(function() {
  // DOM 更新了
});

// 作为一个 Promise 使用
Vue.nextTick().then(function() {
  // DOM 更新了
});

能力检测

按照优先级检测

  1. native promise

  2. MutationObserver(非ie)

  3. setImmediate

  4. setTimeout

官方文档注释中,MutationObserver有更广的适配,但是ie11和UIWebView in iOS >= 9.3.3有严重的bug,所以native promise是第一优先级的

回调队列执行

总体流程就是,接收回调函数,将回调函数推入回调函数队列中。

同时,在接收第一个回调函数时,执行能力检测中对应的异步方法(异步方法中调用了回调函数队列)。

如何保证只在接收第一个回调函数时执行异步方法?

nextTick源码中使用了一个异步锁的概念,即接收第一个回调函数时,先关上锁,执行异步方法。此时,浏览器处于等待执行完同步代码就执行异步代码的情况。

打个比喻:相当于一群旅客准备上车,当第一个旅客上车的时候,车开始发动,准备出发,等到所有旅客都上车后,就可以正式开车了。

当然执行flushCallbacks函数时有个难以理解的点,即:为什么需要备份回调函数队列?执行的也是备份的回调函数队列?

因为,会出现这么一种情况:nextTick套用nextTick。如果flushCallbacks不做特殊处理,直接循环执行回调函数,会导致里面nextTick中的回调函数会进入回调队列。这就相当于,下一个班车的旅客上了上一个班车。

MutationObserver

MutationObserver 如何模拟 nextTick 这点,其实就是创建一个 TextNode 并监听内容变化,然后要 nextTick 的时候去改一下这个节点的文本内容:

最后更新于

这有帮助吗?