前言
可先看EventLoop
具體參見src/core/util/next-tick.js
什么是tick?EvenLoop每一次循環(huán)(一個(gè)mactask、一串mictask)就是一個(gè)tick
正文
flushCallbacks
這里唯一一點(diǎn)是copies,如下所示,要是沒有復(fù)制,那么當(dāng)循環(huán)執(zhí)行到外層回調(diào)時(shí),就會(huì)執(zhí)行內(nèi)部的$nextTick,這時(shí)候內(nèi)層回調(diào)會(huì)被添加到本次tick,也就提前執(zhí)行了
this.$nextTick(() => {
this.$nextTick(() => {
console.log('nest')
})
})
macroTimerFunc、microTimerFunc取舍
在2.4版本之前都是使用microtask,但是在某些情況下它具有太高的優(yōu)先級(jí)并且可能在連續(xù)順序事件之間(#4521,#6690)或者甚至在同一事件的事件冒泡過程中之間觸發(fā)(#6566)。要是全部改成macrotask,對(duì)一些重繪或者動(dòng)畫的場(chǎng)景有性能影響(#6813)。所以在之后的版本默認(rèn)使用microtask,但是有需要(v-on事件處理)強(qiáng)制使用macrotask(src/src/platforms/web/runtime/modules/events.js里的handler = withMacroTask(handler))
macroTimerFunc
macroTimerFunc就三個(gè)選擇,依次降級(jí)setImmediate、MessageChannel、setTimeout
因?yàn)?a target="_blank">setTimeout、timers表現(xiàn),setTimeout調(diào)用間隔至少4ms,實(shí)際上受到任務(wù)隊(duì)列影響,這個(gè)時(shí)間明顯不止,那么沒有最小延遲的setImmediate、MessageChannel明顯更適合了
setImmediate在高版本IE以及Edge才支持
setImmediate
例子
demo
change1與change2區(qū)別在于看flushCallbacks。cbs是順序加入,在改變txt變量(對(duì)應(yīng)的render watcher)之前加入的nextTick執(zhí)行的時(shí)候頁面還未變化,因?yàn)檫@個(gè)render watcher在其之后,頁面還未渲染
