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]
- 依赖收集:渲染时 track 用到的响应式数据
- 触发:set 时 trigger 相关 effect
- 调度:默认异步批处理,合并多次修改
- 渲染:生成新 VNode 树
- 提交:patch 最小必要 DOM
边界
- 详情以当前 Vue3 实现为准,名称是教学模型
watch/watchEffect走副作用路径,不总是等同组件 render- 直接操作 DOM 可能被后续 patch 覆盖
工程实践
- 需要 DOM 测量时用
nextTick - 大列表优化先看更新粒度与 key
- 避免在渲染路径制造新的不必要响应式对象
本节总结
Vue 更新是“响应式通知 + 调度合并 + VDOM 提交”的流水线,不是每个赋值立即同步改 DOM。
自测题
- 为什么多次
qty.value++通常不会同步渲染三次? nextTick解决什么?
参考答案
- 更新调度会合并到同一轮渲染。
- 等待 DOM 提交后再读布局/执行依赖真实 DOM 的逻辑。