全部学科
Python全栈
python
NodeJS全栈
nodejs
📅 2026-05-20 6 分钟 ✍️ juanwangdev

异步更新队列

Vue 在检测到数据变化后,不会立即更新 DOM,而是将更新操作放入异步队列,在下一个事件循环中批量执行。

为什么需要异步更新

JavaScript
// 同步更新的问题
this.count = 1
this.count = 2
this.count = 3
// 如果每次变化都更新DOM,会触发3次渲染

Vue 将多次数据变化合并为一次 DOM 更新,提升性能。

nextTick 实现

JavaScript
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]()
  }
}

// 优先使用微任务(Promise/MutationObserver)
let timerFunc
if (typeof Promise !== 'undefined') {
  const p = Promise.resolve()
  timerFunc = () => p.then(flushCallbacks)
} else {
  // 降级为宏任务 setTimeout
  timerFunc = () => setTimeout(flushCallbacks, 0)
}

function nextTick(cb) {
  callbacks.push(cb)
  if (!pending) {
    pending = true
    timerFunc()
  }
}

Watcher 的异步更新

JavaScript
class Watcher {
  update() {
    // 将更新放入队列
    queueWatcher(this)
  }
}

const queue = []
const has = {}

function queueWatcher(watcher) {
  const id = watcher.id
  if (has[id] == null) {
    has[id] = true
    queue.push(watcher)
    // 下一个tick统一执行
    nextTick(flushSchedulerQueue)
  }
}

function flushSchedulerQueue() {
  // 按优先级排序
  queue.sort((a, b) => a.id - b.id)
  for (let i = 0; i < queue.length; i++) {
    queue[i].run()
  }
  queue.length = 0
}

使用 nextTick

JavaScript
// 场景:数据更新后立即操作DOM
this.message = 'updated'
// 此时DOM还未更新
console.log(this.$el.textContent) // 旧值

this.$nextTick(() => {
  console.log(this.$el.textContent) // 新值
})

// 或使用 async/await
await this.$nextTick()
console.log(this.$el.textContent)

Vue 3 的 flushQueue

JavaScript
import { nextTick, ref } from 'vue'

const count = ref(0)

function increment() {
  count.value++
  // DOM 还未更新
  nextTick(() => {
    // DOM 已更新
  })
}

事件循环中的执行顺序

text
同步代码执行 → 微任务执行(Promise.then)→ DOM更新 → 宏任务执行(setTimeout)
     ↑                                    ↑
  this.count = 1                    nextTick 回调

要点总结

  • Vue 将DOM更新放入异步队列,批量执行避免重复渲染
  • 优先使用微任务(Promise),降级使用宏任务(setTimeout)
  • 多个相同 Watcher 的更新会被去重合并
  • $nextTick 用于获取更新后的DOM状态
想在手机上练习这篇文章的配套题目?
使用微信卷王开发者小程序,打开首页顶部扫码功能识别二维码
← 上一篇 虚拟DOM与Diff算法
下一篇 → v-for与key的作用
扫码体验小程序
加载中
想在手机上刷题学习?
使用微信卷王开发者小程序,打开首页顶部扫码功能识别二维码