Vue 3:虚拟 DOM、diff、优化与 Vue2 / React 对比
一、虚拟 DOM
VNode 用 JS 描述 UI;更新时生成新树,与旧树 diff,再 patch 真实 DOM。
优势
- 批量最小化 DOM 写入。
- 抽象渲染后端(Web / 小程序等)。
Vue 3 工作流程补充
- 编译器标记动态节点(PatchFlag)。
- diff 时跳过纯静态子树。
- 列表采用 最长递增子序列(LIS) 减少移动次数。
二、Vue 3 diff 相对 Vue 2
编译期
- PatchFlags:只比对变化的属性/ children 动态部分。
- 静态提升(hoistStatic):静态节点提到渲染函数外复用。
- 事件缓存:避免无谓的函数重建(与编译实现相关)。
运行时列表
- Vue 2:双端比较。
- Vue 3:预处理两端相同前缀/后缀 + key 映射 + LIS 减少移动。
三、自动优化 vs 手动优化
编译器已做
静态提升、PatchFlag、事件缓存、Tree-shaking 等。
手写侧
- shallowRef / shallowReactive / markRaw 控制代理深度。
- 路由与组件懒加载。
- keep-alive 缓存存活实例。
- computed 缓存计算;watch 监听粒度尽量细。
- 列表:唯一 key、虚拟滚动、
v-memo(Vue 3)等。 v-pre/v-cloak:跳过编译、防闪烁。
四、跨框架 diff 对照说明
列表策略
- Vue 2:双指针四向尝试。
- Vue 3:LIS 最小移动。
- React:单向扫描 + key Map(不自带 Vue3 那种 LIS 移动最优策略)。
共同点
- 跨层移动通常视作删除 + 新建。
- key 都是识别节点身份的核心。
patch 与异步队列
单次响应式 tick 内可能合并多次数据变更,但 patch 递归过程中仍是「对比一段、更新一段」;与「队列合并」解决的是触发次数,不是 patch 内部递归形态。
五、小结
- 虚拟 DOM 提供可 diff 的中间表示。
- Vue 3 把大量优化前移到编译期。
- 列表性能:稳定 key + 合理数据结构;极长列表用虚拟化。
下一章:TypeScript·SSR·错误。
