vue nexttick的实现
Vue nextTick 的实现原理
Vue 的 nextTick 是一个用于在下次 DOM 更新循环结束之后执行延迟回调的方法。它的核心实现依赖于 JavaScript 的事件循环机制,尤其是微任务(microtask)和宏任务(macrotask)的调度。

核心机制
Vue 通过将回调函数推入一个队列,并在适当的时机执行这些回调。具体实现中,Vue 会根据当前环境选择最优的异步调度方式:

- Promise(微任务):现代浏览器支持 Promise,优先使用
Promise.resolve().then(callback)。 - MutationObserver(微任务):如果 Promise 不可用,尝试使用 MutationObserver。
- setImmediate(宏任务):Node.js 环境中使用
setImmediate。 - setTimeout(宏任务):作为最后的备选方案,使用
setTimeout(callback, 0)。
代码实现
以下是 Vue 2.x 中 nextTick 的简化实现逻辑:
let 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]();
}
}
function nextTick(cb, ctx) {
callbacks.push(() => {
if (cb) {
try {
cb.call(ctx);
} catch (e) {
handleError(e, ctx, 'nextTick');
}
}
});
if (!pending) {
pending = true;
if (typeof Promise !== 'undefined') {
Promise.resolve().then(flushCallbacks);
} else if (typeof MutationObserver !== 'undefined') {
const observer = new MutationObserver(flushCallbacks);
const textNode = document.createTextNode(String(counter));
observer.observe(textNode, {
characterData: true
});
textNode.data = String((counter + 1) % 2);
} else if (typeof setImmediate !== 'undefined') {
setImmediate(flushCallbacks);
} else {
setTimeout(flushCallbacks, 0);
}
}
}
使用场景
nextTick 主要用于以下场景:
- 在 Vue 更新 DOM 后立即操作 DOM。
- 确保在数据变化后,DOM 已经更新完毕再执行某些逻辑。
this.message = 'updated';
this.$nextTick(() => {
console.log('DOM updated:', this.$el.textContent);
});
注意事项
- 微任务优先于宏任务执行,因此
nextTick的回调会在当前事件循环的微任务阶段执行,比setTimeout更早。 - 在 Vue 3 中,
nextTick的实现更加简化,直接使用Promise,不再考虑降级方案。
通过这种机制,Vue 确保了视图更新和用户回调的执行顺序,避免了潜在的竞争条件。






