初步认识nextTick
首先 我们要知道为什么vue中有nextTick?
因为在vue框架中采用的是异步更新,当我们监听到数据发生变化时并不会立即更新DOM,而是开启一个任务队列,并缓存在同一时间循环中进行更新;好处是我们可以将多次更新合并成一次,以此来减少DOM的更新,众说周知,频繁的DOM更新是很消耗性能的。
nextTick的作用和实现原理又是什么
nextTick是接受一个回调函数作为参数,并将这个回调函数延迟到DOM更新后才开始执行(简单理解就是我们做了一个延时器,将多个事件延迟到DOM更新后开始执行这些事件)。 nextTick是将传入的回调函数包装成异步任务,而在异步任务中又分为宏任务和微任务,为了尽快执行所以优先选择异步任务中的微任务来执行。
源码解读
以上就是nextTick源代码,下面我们来分析一下
第一步 先准备一个存储回调函数的队列,再准备一个执行函数
首先声明了一个callbacks 用来存储回调函数的队列 , 同时写了一个flushCallbacks作为执行函数
第二步 逐步分析一下nextTick函数
这一步就很明了了 ,回调函数cb部位空 则推进到队列cllbacks中
pending为false,执行函数timerFunc下一段代码分析它
我们再看一下timerFunc这个函数又做了什么,先看代码
这里出现了好几个isNative函数,这是用来判断所传参数是否在当前环境原生就支持;例如某些浏览器不支持Promise,虽然我们使用了垫片(polify),但是isNative(Promise)还是会返回false。
可以看出这边代码其实是做了四个判断,对当前环境进行不断的降级处理,尝试使用原生的Promise.then、MutationObserver和setImmediate,上述三个都不支持最后使用setTimeout;降级处理的目的都是将flushCallbacks函数放入微任务(判断1和判断2)或者宏任务(判断3和判断4),等待下一次事件循环时来执行。MutationObserver是Html5的一个新特性,用来监听目标DOM结构是否改变,也就是代码中新建的textNode;如果改变了就执行MutationObserver构造函数中的回调函数,不过是它是在微任务中执行的。
代码分析到这里我们也可以看出,nextTick根本目的是为了将flushCallbacks放到宏任务或者微任务中去执行,flushCallbacks我们上边分析过,它所做的事情也非常的简单,把callbacks数组复制一份,然后把callbacks置为空,最后把复制出来的数组中的每个函数依次执行一遍;所以它的作用仅仅是用来执行callbacks中的回调函数。
总结
整体nextTick的代码都分析完毕了,总结一下它的整个流程就是
- 把回调函数放入callbacks等待执行
- 将执行函数放到微任务或者宏任务中
- 事件循环到了微任务或者宏任务,执行函数依次执行callbacks中的回调
这就是整个nextTick的执行逻辑