Vue3推荐使用模板而非JSX,核心在于模板可被编译器静态分析生成Block Tree,实现细粒度更新;而JSX作为运行时JavaScript,无法参与Block构建,导致diff退化为全量比对。

Vue3 推荐使用模板(template)而非 JSX,核心原因在于模板能充分利用编译期的 Block Tree 优化机制,而 JSX 在当前 Vue 生态中无法参与这一关键优化链路。
Block Tree 是什么?
Block Tree(块树)是 Vue3 编译器在构建阶段对模板进行静态分析后生成的一种结构化中间表示。它将整个组件的 DOM 树按“更新边界”划分为若干逻辑块(block),每个 block 内部只包含具有相同响应式依赖或更新频率的节点,并打上 PatchFlag(如 TEXT、PROPS、DYNAMIC_CHILDREN 等)。运行时 diff 过程中,Vue 只需遍历这些 block,跳过完全静态的部分,极大减少比对开销。
模板天然适配 Block Tree
模板语法的声明式、受限性,使其具备强可分析性,编译器能稳定识别:
- 哪些节点完全静态(如纯文本、无绑定属性的标签)→ 提升为 hoisted 节点,仅创建一次
- 哪些属性是动态绑定 → 自动标记为 PATCHED 或 PROPS
- 哪些子节点可能整体替换(如 v-if/v-for 切换)→ 封装为独立 block,支持整块卸载/挂载
- v-on 内联处理器自动缓存 → 避免因函数引用变化导致子组件误更新
JSX 无法生成 Block Tree
JSX 是 JavaScript 表达式,Babel 插件(如 @vitejs/plugin-vue-jsx)仅将其转为 h() 函数调用链,不执行深度静态分析:
- 所有节点都以运行时 h() 调用构造 → 每次渲染都新建 VNode,无静态提升
- 无法自动推导 PatchFlag → 即使某段 JSX 完全静态,也会被当作 FULL_PROPS 处理,diff 时逐属性比对
- 条件与循环靠 JS 原生语法(如 &&、map)实现 → 编译器无法识别其语义边界,block 划分失效
- 事件处理器常写为箭头函数(
() => doSomething())→ 每次渲染生成新引用,触发不必要的子组件重渲染
性能影响直接体现在三方面
Block Tree 的缺失,让 JSX 在实际运行中承受更高成本:
- 首次渲染慢:无 hoist,重复创建大量静态 VNode;产物体积更大(含 _hoist、_createBlock 等辅助函数)
- 更新效率低:缺少 PatchFlag 指引,diff 需遍历更多节点;无法跳过整块静态内容
- 内存压力高:频繁构造/丢弃 VNode 对象,GC 压力上升,尤其在长列表滚动场景下明显
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











