- 异步:只要侦听到数据变化,Vue 将开启⼀个队列,并缓冲在同⼀事件循环中发⽣的所有数据变更。
- 批量:如果同⼀个 watcher 被多次触发,只会被推⼊到队列中⼀次。去重对于避免不必要的计算 和 DOM 操作是⾮常重要的。然后,在下⼀个的事件循环“tick”中,Vue 刷新队列执⾏实际⼯作。
- 异步策略:Vue 在内部对异步队列尝试使⽤原⽣的
Promise.then
、MutationObserver
或setImmediate
,如果执⾏环境都不⽀持,则会采⽤setTimeout
代替。
core\observer\watcher.js
dep.notify()之后watcher执⾏更新,执⾏⼊队操作
update () {
/* istanbul ignore else */
// computed
if (this.lazy) {
this.dirty = true
} else if (this.sync) {
this.run()
} else {
// 入队
queueWatcher(this)
}
}
core\observer\scheduler.js
执⾏watcher⼊队操作
export function queueWatcher (watcher: Watcher) {
// 去重
const id = watcher.id
// 不存在才入队
if (has[id] == null) {
has[id] = true
if (!flushing) {
queue.push(watcher)
} else {
// if already flushing, splice the watcher based on its id
// if already past its id, it will be run next immediately.
let i = queue.length - 1
while (i > index && queue[i].id > watcher.id) {
i--
}
queue.splice(i + 1, 0, watcher)
}
// queue the flush
if (!waiting) {
waiting = true
if (process.env.NODE_ENV !== 'production' && !config.async) {
flushSchedulerQueue()
return
}
// 异步执行flushSchedulerQueue
nextTick(flushSchedulerQueue)
}
}
}
core\util\next-tick.js
nextTick按照特定异步策略执⾏队列操作
就是Vue.nextTick $nextTick把传入回调函数放入 callback 队尾
// 回调函数数组
const callbacks = []
let pending = false
// 刷新回调函数数组
function flushCallbacks () {
pending = false
const copies = callbacks.slice(0)
callbacks.length = 0
// 遍历并执行
for (let i = 0; i < copies.length; i++) {
copies[i]()
}
}
// 将cb函数放入回调队列队尾
export function nextTick (cb?: Function, ctx?: Object) {
let _resolve
callbacks.push(() => {
if (cb) {
try {
cb.call(ctx)
} catch (e) {
handleError(e, ctx, 'nextTick')
}
} else if (_resolve) {
_resolve(ctx)
}
})
if (!pending) {
pending = true
// 异步执行函数
timerFunc()
}
// $flow-disable-line
if (!cb && typeof Promise !== 'undefined') {
return new Promise(resolve => {
_resolve = resolve
})
}
}
timerFunc()
if (typeof Promise !== 'undefined' && isNative(Promise)) {
//首选Promise
const p = Promise.resolve()
timerFunc = () => {
p.then(flushCallbacks)
...
}
参考: http://www.booleanln.top/2019/09/14/nextTick%E6%B5%85%E6%9E%90/ https://ppt.baomitu.com/d/0052678d https://juejin.cn/post/6930413268376748045 https://github.com/ziyi2/ziyi2.github.io/issues/5