vue组件更新流程为:数据变化→队列调度→重新渲染→虚拟dom对比→真实dom更新;仅响应式数据变更触发更新,通过异步批处理与diff算法实现高效dom操作。

Vue 组件更新不是“一改就刷屏”,而是一套有明确先后顺序的协作流程:数据变化 → 队列调度 → 重新渲染 → 虚拟 DOM 对比 → 真实 DOM 更新。整个过程严格按阶段推进,且关键步骤(如 diff)只在特定时机触发。
响应式变化是更新的唯一起点
只有当被 Vue 响应式系统追踪的数据(data、props、computed 依赖项)发生修改时,更新流程才会启动。普通变量赋值、未声明在 data 中的属性、或通过 Object.assign 直接替换整个对象(未做响应式处理)都不会触发更新。
- Vue 2 使用
Object.defineProperty拦截 setter;Vue 3 使用Proxy捕获所有操作 - 每次修改都会通知对应组件的 watcher,但不会立即执行 render,而是标记为“待更新”并推入异步队列
- 多个同步修改会被合并为一次更新,避免重复计算和渲染
diff 发生在 patch 阶段,且仅限已有 DOM 的更新场景
diff 算法只在组件已挂载、存在旧虚拟 DOM(oldVnode)时运行。首次渲染(mount)不走 diff,而是直接调用 createElm 生成真实 DOM 并插入页面。
- diff 的输入是两个 VNode:当前组件实例保存的
_vnode(旧树)与render()新生成的 VNode(新树) - 对比从根节点开始,逐层向下;若节点 tag 或 key 不同,直接销毁旧节点 + 插入新节点(不递归子树)
- 列表更新时,key 是 diff 正确复用节点的前提;缺失 key 会导致就地更新,可能引发状态错乱(如 input 失焦、动画中断)
更新是异步批处理,nextTick 是观察时机的关键
Vue 把所有待更新组件收集到一个队列中,在下一个宏任务(microtask)末尾统一执行,这就是 nextTick 的作用基础。
- 在
vm.$nextTick(() => {...})回调中,可确保 DOM 已完成本次更新(包括 diff 后的 patch) - 连续多次
this.count++只会触发一次 diff + patch,而非三次 - 若需在数据变更后立刻读取更新后的 DOM 尺寸或位置,必须等待 nextTick
patch 是 diff 的执行载体,决定最终 DOM 操作类型
patch(oldVnode, vnode) 函数封装了整个更新逻辑,它根据节点差异选择最小代价操作:
- 文本节点变化 → 修改
textContent - 元素属性变化 → 增删/更新
setAttribute或事件监听器 - 子节点结构变化 → 进入
updateChildren,执行双端 Diff(头-头、尾-尾、旧头-新尾、旧尾-新头) - 节点完全不兼容(如
div→span)→replaceChild替换整块 DOM
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











