block tree 是对虚拟 dom 的结构性升级,通过静态提升跳过静态节点 diff、dynamicchildren 精准定位动态节点、patchflag 优化比对路径,并依赖编译期静态分析实现“编译即优化”。

Block Tree 不是替代虚拟 DOM,而是对它的结构性升级。它把原本“整棵树统一 diff”的粗粒度模式,变成“按块分区、靶向更新”的细粒度策略,这才是 Vue 3 性能飞跃的核心逻辑。
静态内容彻底跳过 diff
传统虚拟 DOM 每次更新都会重建整个 VNode 树,哪怕只是改了一个输入框的值,页脚的版权文字也要跟着重新创建和比对。Block Tree 在编译阶段就识别出纯静态节点(比如 <p>© 2024</p>),把它们提升为常量,在 render 函数外单独定义。运行时直接复用,完全不参与 diff 流程。
- 静态提升(Static Hoisting)让这部分节点只创建一次,内存中长期持有
- 避免了无意义的 VNode 构造、属性比对、GC 回收等开销
- 模板越长、静态内容越多,节省越明显
动态节点精准定位更新
Block Tree 给每个 Block 标记 dynamicChildren 数组,里面只存真正会变的 VNode。更新时,diff 算法不再遍历整棵树,而是直奔这个数组——相当于从“大海捞针”变成“抽屉找物”。
- 每个 Block 自带
patchFlag(如TEXT=1、CLASS=2),标明哪些属性可能变化 - 运行时根据 flag 跳过无关比对,比如 class 变了就只更新 class,不碰 style 或子节点
- 列表项、条件分支、插槽内容等复杂结构,也能通过嵌套 Block 实现局部收敛
更新路径大幅缩短
传统 diff 是深度优先递归遍历,时间复杂度接近 O(n);Block Tree 把树拆成多个独立更新单元,每次只处理受影响的 Block 及其 dynamicChildren,实际操作节点数显著下降。
- 一个含 50 个节点的组件,若只有 3 个动态节点,Block Tree 更新路径长度≈3,传统方式≈50
- 主线程被阻塞的时间更短,帧率更稳,尤其在高频交互(如拖拽、输入)场景下优势突出
- 配合 V8 的优化机制,小而确定的更新片段更容易被 JIT 编译器高效处理
编译期决定运行时行为
Block Tree 的能力高度依赖编译器的静态分析。Vue 3 的编译器在构建阶段就完成节点分类、flag 标记、hoist 提取等工作,生成的 render 函数里已经固化了最优更新路径。
- 开发者无需手动 memo 或 shouldComponentUpdate,优化由框架自动完成
- 不是靠运行时猜测,而是靠编译时确信——静态内容就是不变,动态绑定就是可追踪
- 这种“编译即优化”的思路,把性能负担从用户代码和运行时,转移到构建工具链中











