Vue.js 不存在名为 BlockTree 的运行时数据结构,“BlockTree”是社区对 Vue 3 编译器将模板切分为独立更新块的优化机制的非正式称呼,其本质是编译时生成嵌套 createBlock() 调用的渲染函数。

Vue.js 并没有内置的 BlockTree 概念,也不存在官方文档或源码中名为 BlockTree 的数据结构用于搜集 v-if 与 v-for 的动态分支。
所谓“BlockTree”是社区对编译优化机制的一种非正式称呼
在 Vue 3 的编译器(@vue/compiler-core)中,模板会被解析为 AST,再经过 transform 阶段生成具有“块语义”(block semantics)的代码。Vue 3 引入了 Block Tree(块树)优化思想,其核心目标是:将模板切分为多个独立更新的“块”(blocks),每个块只包含可能响应式变化的节点,从而缩小 diff 范围、减少 patch 开销。
这个“块”不是运行时真实存在的树形对象,而是编译时生成的嵌套函数调用结构(如 openBlock() / createBlock()),最终形成逻辑上分层的渲染函数。
v-if 与 v-for 的分支如何被“搜集”进块结构
编译器不会“搜集分支”到某个叫 BlockTree 的容器里,而是根据指令语义,在生成渲染函数时自动构造嵌套的 block 调用链:
立即学习“前端免费学习笔记(深入)”;
-
v-if/v-else-if/v-else分支会被分别包裹进独立的createBlock()或条件表达式中,每个分支自身可成为子 block;父 block 通过条件判断决定激活哪个子 block -
v-for会生成一个循环上下文,每次迭代创建的节点(包括内部含v-if的嵌套结构)默认属于该 for-block 的作用域;若循环体内部有响应式依赖,整个 for-block 就是更新边界 - 当
v-if和v-for同时出现在同一元素上(不推荐),Vue 3 编译器会**优先处理v-for**,把v-if下移到每个循环项的根节点内,确保每个列表项的条件判断独立执行,并各自纳入对应的循环块中
关键点:块的划分由编译时静态分析驱动
是否形成新 block,取决于节点是否含有动态绑定、插槽、v-if/v-for 等可导致子树重渲染的特征,而非运行时搜集。例如:
- 静态节点(纯文本、无绑定属性)被提升为
createStaticVNode(),不参与 block 更新 - 带
:key的v-for会触发openBlock(true),启用 keyed block 更新模式 - 顶层组件模板默认是一个 root block;带
v-if的根元素会使其变为 conditional block
本质上,这是编译时的代码生成策略,不是运行时维护一棵 BlockTree 数据结构。所谓“搜集”,实为 AST 遍历过程中依据指令类型插入对应 block 创建/打开/关闭调用的过程。


















