DOM 更新与调度

vue/dom_updates_and_scheduling2026-09-10 22:39:50

Vue 在响应式状态变化后调度组件更新,并把新的渲染结果应用到真实 DOM。状态赋值通常不会在同一行代码中立刻完成 DOM 更新;Vue 会缓冲同一轮中的更新,以避免一个组件因连续多次状态变化而重复更新。

更新批处理

<script setup>
import { ref, nextTick } from 'vue'

const count = ref(0)

async function increment() {
  count.value++
  // 此处 DOM 通常仍是更新前的内容
  await nextTick()
  // 此处相关 DOM 更新已经完成
}
</script>

nextTick() 返回一个 Promise,也可以接收回调。它用于等待当前一批待处理的 DOM 更新完成,而不是强制每一次状态赋值立即同步修改 DOM。

从状态变化到 DOM

一轮典型更新包含以下关系:

修改响应式状态
      ↓
触发依赖该状态的组件更新
      ↓
调度器合并本轮任务
      ↓
重新执行渲染并更新虚拟 DOM
      ↓
将必要变化 patch 到真实 DOM

组件重新渲染不等于整棵真实 DOM 重建。渲染器会根据新旧虚拟节点及编译器提供的信息执行文本、属性、事件监听、节点插入、移动或删除等必要操作。

DOM 更新后的操作

需要读取更新后 DOM 时,可以等待 nextTick(),也可以在适当的生命周期钩子中处理。onUpdated() 会在组件因响应式状态变化完成 DOM 更新后调用,但一次父子组件更新中,子组件的 updated 钩子先于父组件。若只关心某一次特定状态变化,nextTick() 通常能更直接地限定时机。

侦听器也有不同的执行时机。默认侦听器回调发生在所属组件 DOM 更新之前;需要访问更新后的 DOM 时,可以使用 flush: 'post' 或相应的 post-effect API。同步侦听器不会批处理,应避免用于可能被频繁同步修改的数据源。

模板引用

模板引用允许在组件挂载后访问 DOM 元素或子组件实例,适合聚焦、测量或接入第三方库。直接 DOM 操作应限制在必要的命令式边界内;由 Vue 管理的界面内容仍应通过响应式状态和模板表达。

相关官方资料:nextTick()、组件生命周期、侦听器的回调触发时机、模板引用。

本页目录