在 Vue 中,组件的 template
需要被转换为 JavaScript 渲染函数(Render Function)才能在浏览器中运行。Vue 2 和 Vue 3 的转换机制有所不同,主要体现在编译时机、编译工具和输出结果上。
1. Vue 2 的 Template 转换
转换方式
Vue 2 使用 vue-template-compiler
在构建时(通常是 Webpack 的 vue-loader
)将 .vue
文件中的 <template>
编译为渲染函数。
步骤
开发阶段:
通过
vue-loader
处理.vue
文件,提取<template>
部分。使用
vue-template-compiler
将模板编译为render()
函数。最终生成的代码类似:
render(h) {
return h('div', { attrs: { id: 'app' } }, 'Hello World');
}
2.运行时:
- 如果未预编译(如直接使用
template: '<div>Hello</div>'
选项),Vue 2 会在浏览器中动态编译(需要包含完整版 Vue,体积较大)。
关键点
依赖:
vue-template-compiler
(必须与 Vue 2 版本严格匹配)。输出:渲染函数使用
h
(即createElement
)生成虚拟 DOM。动态编译:完整版 Vue(含编译器)支持运行时编译,但推荐预编译以优化性能。
2. Vue 3 的 Template 转换
转换方式
Vue 3 使用 @vue/compiler-sfc
(单文件组件编译器)和 @vue/compiler-dom
(模板编译器),编译过程更高效且支持更多优化。
步骤
开发阶段:
@vue/compiler-sfc
解析.vue
文件,分离<template>
、<script>
、<style>
。@vue/compiler-dom
将模板编译为 优化后的渲染函数。生成的代码使用
import { createVNode } from 'vue'
,例如:
import { createVNode as _createVNode } from 'vue';
export function render(_ctx, _cache) {
return _createVNode('div', { id: 'app' }, 'Hello World');
}
2.运行时:
- Vue 3 不再支持浏览器内的动态模板编译(即使使用完整版),所有模板必须预编译。
- 渲染函数直接使用
createVNode
(替代 Vue 2 的h
)。
关键点
依赖:
@vue/compiler-sfc
(Vite 或 Vue CLI 内部集成,无需手动配置)。输出:渲染函数更高效,支持静态节点提升(Static Hoisting)、补丁标志(Patch Flags)等优化。
体积更小:由于移除了运行时编译器,生产包更精简。
3. Vue 2 和 Vue 3 的主要区别
特性 | Vue 2 | Vue 3 |
---|---|---|
编译器工具 | vue-template-compiler |
@vue/compiler-sfc |
运行时编译 | 支持(需完整版 Vue) | 不再支持(必须预编译) |
渲染函数生成 | h(createElement) |
createVNode |
优化策略 | 基础虚拟 DOM 优化 | 静态提升、补丁标志等高级优化 |
体积影响 | 完整版含编译器,体积较大 | 更精简(无运行时编译器) |
总结
Vue 2:
依赖
vue-template-compiler
,支持运行时编译(但推荐预编译)。渲染函数使用
h
,优化较少。
Vue 3:
依赖
@vue/compiler-sfc
,强制预编译,渲染函数使用createVNode
。编译时优化更多,性能更好,包体积更小。
最佳实践:无论 Vue 2 还是 Vue 3,都应通过构建工具(Webpack/Vite)预编译模板,避免运行时开销。