Vue 模板如何变成可执行的 render function?
Vue 模板编译的核心流程可以概括为:
浏览器不能直接理解 Vue 的模板语法:
Vue 需要把模板转换成 JavaScript render function。组件运行时执行 render function,生成 VNode,再由 renderer 将 VNode patch 到真实 DOM。
Parse 阶段会读取模板字符串,识别:
例如:
会被解析成类似这样的 AST:
AST 是后续分析和生成代码的中间表示。
Transform 阶段会遍历 AST,将模板语义转换成运行时需要的信息,例如:
v-if 转换为条件表达式;v-for 转换为列表渲染逻辑;Vue 3 会在这里生成 Patch Flag、Block 等优化信息,让运行时只关注真正可能变化的部分。
最终会生成近似下面的逻辑:
实际 Vue 3 编译产物会使用 openBlock、createElementBlock 等内部函数,并附带动态节点标记。这里的代码只是帮助理解的简化版本。
不会变化的 VNode 或 props 可以提升到 render function 外部,避免每次渲染重复创建。
编译器可以标记节点的动态部分,例如只有文本变化、只有 class 变化或只有事件变化。运行时不必重新检查所有属性。
Block 会收集动态后代,更新时优先遍历动态节点,减少无关子树的比较。
部分静态事件处理器可以被缓存,减少每次 render 创建新函数的成本。
现代 Vue 项目通常使用 SFC 编译器在构建阶段处理 <template>。
key 和合理的组件边界。Vue 模板会先经过 Parse 生成 AST,再经过 Transform 完成指令转换和静态分析,最后由 Codegen 生成 render function。运行时执行 render function 生成 VNode,renderer 再通过 patch 更新 DOM。Vue 3 还通过静态提升、Patch Flag 和 Block Tree 缩小运行时更新范围。