vue响应式更新非同步执行,而是经依赖通知、异步队列、微任务调度、render重执行、vnode diff、dom patch六步协作完成,最终由浏览器渲染流水线决定画面更新时机。

Vue 响应式数据不是“一改就立刻画到屏幕上”,它和浏览器渲染流水线之间存在明确的协作节奏:数据变化 → 依赖通知 → 异步更新队列 → 微任务调度 → render 重执行 → VNode diff → DOM patch。这个链条里,每一步都不可跳过,也都有其设计意图。
响应式系统是变化的“感知器”
Vue 3 使用 Proxy 劫持对象属性,在 get 阶段收集当前正在运行的渲染 effect(即组件的 render 函数),在 set 阶段触发该 effect 重新执行。这意味着:
- 只有被 render 函数实际读取过的响应式字段,才会建立依赖关系
- 直接添加未声明的属性(如
state.newField = 'x')不会触发更新,因为没被 track 过 -
ref和reactive创建的数据,底层都接入同一套依赖追踪机制(Dep + effect)
更新不是同步执行,而是进队列等微任务
当你修改一个响应式值,Vue 不会马上重渲染。它把对应的 effect 标记为“待更新”,推入一个异步更新队列,并用 Promise.then 或 MutationObserver 包装成微任务(即 $nextTick 的底层)。这样做的好处是:
- 同一轮事件循环中多次修改同一数据,只触发一次 re-render
- 避免 render 中间态 DOM 被反复创建/销毁,提升性能
- 保证你在
$nextTick回调里能拿到更新后的 DOM(比如日历组件挂载后立即聚焦日期单元格)
虚拟 DOM 是更新的“执行层”,不是万能缓存
每次 effect 重执行,都会生成一棵新的 VNode 树。Vue 并不比对整棵树,而是利用编译阶段打上的 PatchFlag 和 Block Tree 结构,只遍历动态节点数组:
- 静态内容(如固定文字、class)在编译时已提升,render 中不参与响应式依赖收集
- 动态绑定(
v-bind:class、{{ count }})带 PatchFlag,diff 时直奔目标节点 - 子节点更新采用双端 Diff + LIS 算法,尽量复用已有 DOM 元素,减少移动和重建
浏览器渲染流水线才是最终“拍板人”
Vue 的 patch 操作完成后,真实 DOM 已变更,但屏幕是否立刻重绘,取决于浏览器自身的渲染帧节奏:
- 如果 Vue 更新发生在当前帧的 JS 执行阶段末尾,浏览器可能在下一帧统一 layout + paint
- 若中间触发了强制同步布局(如读取
offsetHeight),会导致重排提前,打断优化 - 动画类操作建议配合
requestAnimationFrame,与浏览器帧对齐,而非依赖 Vue 的 nextTick
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











