vue nexttick 实现
Vue nextTick 实现原理
Vue 的 nextTick 是一个用于在下次 DOM 更新循环结束之后执行延迟回调的方法。它主要用于确保在 DOM 更新完成后执行某些操作。
核心实现机制
nextTick 的实现基于 JavaScript 的事件循环机制,利用微任务(microtask)或宏任务(macrotask)来延迟回调的执行。
Vue 会根据当前环境选择最合适的延迟策略:
- 优先使用
Promise(微任务) - 降级到
MutationObserver(微任务) - 再降级到
setImmediate(宏任务) - 最后使用
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 if (typeof setImmediate !== 'undefined') {
timerFunc = () => {
setImmediate(flushCallbacks)
}
} 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
})
}
}
使用场景
-
在数据变化后操作更新后的 DOM
this.message = 'updated' this.$nextTick(() => { // DOM 现在已经更新 }) -
在组件中使用
this.$nextTick().then(() => { // DOM 更新完成后的操作 })
注意事项
nextTick返回一个 Promise,可以使用 async/await 语法- 多次调用
nextTick的回调会在同一个 tick 中执行 - 确保在正确的生命周期中使用,避免不必要的性能开销







