Vue 渲染与更新流程

从状态变更到 DOM 更新的主链路:依赖收集、触发、调度、虚拟 DOM patch。

#type / synthesis #status / growing #tech / dev / frame #resource / vue3

[!info] 关联笔记

Vue 渲染与更新流程

这个概念为什么出现

只知道 ref 一改页面会变,却说不清:

  • 为什么多次修改只渲染一次
  • nextTick 为何存在
  • 组件更新边界在哪

需要一条从响应式触发到 DOM patch 的主链路。

[!abstract] 一句话理解 状态变更 → 触发依赖 → 调度组件更新任务 → 重新渲染 VNode → patch 到 DOM。

最小可观察示例

场景:连点扫码三次

<script setup>
import { ref, nextTick } from 'vue'
const qty = ref(0)

async function scanBurst() {
  qty.value++
  qty.value++
  qty.value++
  // 教学点:同步代码里 DOM 可能尚未更新
  await nextTick()
  console.log('DOM text now reflects', qty.value)
}
</script>

<template>
  <button type="button" @click="scanBurst">{{ qty }}</button>
</template>

期望:同步三次自增后,更新被批处理;nextTick 后可读到提交后的 DOM。

核心链路

flowchart LR
  A[改 ref/reactive] --> B[trigger 依赖]
  B --> C[scheduler 排队]
  C --> D[组件 render 出 VNode]
  D --> E[diff/patch DOM]
  1. 依赖收集:渲染时 track 用到的响应式数据
  2. 触发:set 时 trigger 相关 effect
  3. 调度:默认异步批处理,合并多次修改
  4. 渲染:生成新 VNode 树
  5. 提交:patch 最小必要 DOM

边界

  • 详情以当前 Vue3 实现为准,名称是教学模型
  • watch/watchEffect 走副作用路径,不总是等同组件 render
  • 直接操作 DOM 可能被后续 patch 覆盖

工程实践

  • 需要 DOM 测量时用 nextTick
  • 大列表优化先看更新粒度与 key
  • 避免在渲染路径制造新的不必要响应式对象

本节总结

Vue 更新是“响应式通知 + 调度合并 + VDOM 提交”的流水线,不是每个赋值立即同步改 DOM。

自测题

  1. 为什么多次 qty.value++ 通常不会同步渲染三次?
  2. nextTick 解决什么?
参考答案
  1. 更新调度会合并到同一轮渲染。
  2. 等待 DOM 提交后再读布局/执行依赖真实 DOM 的逻辑。
创建于 2026/3/19 更新于 2026/7/15