认识
一、认识
nextTick
在下次 DOM
更新循环结束之后执行延迟回调。一般用于修改数据之后, 立即使用 nextTick
获取更新后的 DOM
。Vue
有个机制,更新 DOM
是异步执行的,当数据变化会产生一个异步更行队列,要等异步队列结束后才会统一进行更新视图,所以改了数据之后立即去拿 DOM
还没有更新就会拿不到最新数据。所以提供了一个 nextTick
函数,它的回调函数会在DOM
更新后立即执行。
二、Vue.js 2.0
Vue.js 2.0
$nextTick
工作流:
-
调用
dep.notify()
触发依赖通知更新,将负责更新的watcher
放入watcher
队列, 这个队列为flushSchedulerQueue
-
用
try catch
包装flushSchedulerQueue
更新函数或者用户传入的回调函数,然后将其放入callbacks
数组。存放flushSchedulerQueue
的callbacks
数组我们叫做**更新DOM
**的数组 -
这时候, 我们调用
Vue.nextTick(cb)
, 将用户cb
加入callbacks
, 这个callbacks
数组我们叫做用户回调数组 -
如果
pending
为false
,表示现在浏览器的任务队列中没有flushCallbacks
函数, 将pending
置为true
, 执行timeout
函数, 浏览器的任务队列中加入flushCallbacks
函数, 执行callbacks
数组中的每一个函数, 进而执行watcher.run()
更新DOM
, 随后清空callbacks
数组 -
待执行
flushCallbacks
完函数时,pending
会被再次置为false
,表示下一个flushCallbacks
函数可以进入浏览器的任务队列了, 开始执行用户callbacks
数组, 这样可以保证先完成的DOM
更新,再执行cb
函数。
2.1 pending
pending
: 保证在同一时刻,浏览器的任务队列中只有一个 flushCallbacks
函数
2.2 添加回调
把传入的回调函数 cb
压入 callbacks
数组
2.3 执行 timeFunc
执行timeFunc
函数,通过微任务或者宏任务将flushCallbacks
加入到任务队列。其中, timeFunc
函数的优雅降级策略为:
-
微任务
Promise.then
-
微任务
MutationObserver
: 创建一个MutationObserver
对象, 并且把flushCallbacks
作为MutationObserver
构造函数的回调函数。之后我们创建一个文本节点, 通过mutationObserver.observe()
来监听该文本节点, 如果文本节点的内容有任何变动的话, 它就会触发flushCallbacks
回调函数。因此, 我们只需要timerFunc
函数中, 修改文本内容, 文本节点内容发生变化之后, 进而触发MutationObserver
的回调。 -
宏任务
setImmediate
-
宏任务
setTimeout