返回首页

关于nextTick

布莱克2026-05-15 09:57已编辑
Tip:文章封面与内容无关,作者旅游时拍摄,因为没什么值得把四季都错过!

为什么需要 nextTick?

首先在 Vue 中,DOM 的更新是异步的,操作真实的 DOM 是极其昂贵的。频繁地触发浏览器的**重排(Reflow)重绘(Repaint)**会导致明显的卡顿

  • 如果是同步更新:Vue 会监听到 1000 次数据变化,触发 1000 次虚拟 DOM 计算,并执行 1000 次真实的 DOM 操作。浏览器会因此崩溃。

异步更新机制:

『同步收集依赖、异步刷新队列』的策略,以 JS 执行栈清空为界限进行 DOM 派发。一旦遇到异步边界(Async Boundary),则会自动触发当前生命周期的微任务刷新

当你修改了响应式数据(例如 count.value++),Vue 并不会立即去更新 DOM 节点,而是:

  1. 开启一个异步观察队列。
  2. 缓冲在同一事件循环中发生的所有数据变更。
  3. 如果同一个 watcher 被多次触发,只会被推入队列一次。
  4. 在下一个“tick”中,Vue 刷新队列并执行实际的 DOM 更新。

如果你在修改数据后立即尝试获取 DOM 的内容,拿到的将是旧数据,nextTick 就是为了可以在“DOM 更新完成”这个时机点执行回调

DOM 更新操作本身是什么?一个微任务
这个微任务是谁创建的?Vue 内部自动创建的(用 nextTick + Promise
需要手动写 Promise.then 才能触发吗?不需要,Vue 会自动创建并调度
同步代码结束后这个微任务会执行吗?,事件循环会自动清空微任务队列
如果没有任何数据修改,会有这个微任务吗?不会,没有数据修改就不会创建


底层实现:

Vue 2 的内部实现是一个典型的**优先微任务(Microtask)**的降级方案。为了确保回调尽可能早地执行,它会按以下顺序探测浏览器支持的异步 API:

  1. Promise.then (微任务)
  2. MutationObserver (微任务)
  3. setImmediate (宏任务,IE 特有)
  4. setTimeout(fn, 0) (宏任务,兜底)

Vue 3 抛弃了复杂的降级逻辑,直接使用 Promise

原因: Vue 3 针对的是现代浏览器,这些环境百分之百支持 Promise


assistant