vue nexttick实现
Vue 中 nextTick 的实现原理
Vue 的 nextTick 是一个用于在下次 DOM 更新循环结束之后执行延迟回调的工具方法。它利用了 JavaScript 的事件循环机制,确保回调在 DOM 更新完成后执行。
核心实现机制
Vue 的 nextTick 实现依赖于微任务(microtask)和宏任务(macrotask)的优先级。在现代浏览器中,优先使用 Promise(微任务),如果不支持则降级到 MutationObserver,最后使用 setTimeout(宏任务)。
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]()
}
}
let timerFunc
if (typeof Promise !== 'undefined') {
const p = Promise.resolve()
timerFunc = () => {
p.then(flushCallbacks)
}
} else if (typeof MutationObserver !== 'undefined') {
let counter = 1
const observer = new MutationObserver(flushCallbacks)
const textNode = document.createTextNode(String(counter))
observer.observe(textNode, {
characterData: true
})
timerFunc = () => {
counter = (counter + 1) % 2
textNode.data = String(counter)
}
} else {
timerFunc = () => {
setTimeout(flushCallbacks, 0)
}
}
function nextTick(cb, ctx) {
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()
}
if (!cb && typeof Promise !== 'undefined') {
return new Promise(resolve => {
_resolve = resolve
})
}
}
使用场景
nextTick 主要用于在 Vue 更新 DOM 后执行某些操作。例如,在修改数据后立即操作 DOM 元素:
this.message = 'updated'
this.$nextTick(() => {
// DOM 已更新
console.log(this.$el.textContent) // 'updated'
})
异步更新队列
Vue 在更新 DOM 时是异步执行的。当数据变化时,Vue 开启一个队列,缓冲在同一事件循环中发生的所有数据变更。如果一个 watcher 被多次触发,只会被推入队列一次。在下一个事件循环“tick”中,Vue 刷新队列并执行实际工作。
nextTick 就是将回调函数添加到这个队列的末尾,确保在 DOM 更新完成后执行。







