vue compile源码实现
Vue 编译源码实现解析
Vue 的编译过程主要分为模板解析、优化和代码生成三个阶段。以下是核心实现逻辑的拆解:
模板解析阶段
通过 parse 函数将模板字符串转换为 AST(抽象语法树)。关键步骤包括:
- 使用正则表达式匹配标签、属性、指令等模板语法
- 解析器通过栈结构维护标签嵌套关系
- 生成带有节点类型、属性、子节点等信息的 AST 节点
// 简化后的解析逻辑示例
function parse(template) {
const stack = []
let root, currentParent
parseHTML(template, {
start(tag, attrs) {
const element = createASTElement(tag, attrs)
if (!root) root = element
if (currentParent) currentParent.children.push(element)
stack.push(element)
currentParent = element
},
end() {
stack.pop()
currentParent = stack[stack.length - 1]
}
})
return root
}
优化阶段
通过 optimize 函数对 AST 进行静态标记:
- 标记静态节点(永远不会变化的节点)
- 标记静态根节点(包含静态子节点的父节点)
- 为后续 patch 过程跳过静态节点优化性能
function optimize(root) {
markStatic(root)
markStaticRoots(root)
}
function markStatic(node) {
node.static = isStatic(node)
if (node.children) {
node.children.forEach(child => {
markStatic(child)
if (!child.static) node.static = false
})
}
}
代码生成阶段
通过 generate 函数将 AST 转换为可执行的渲染函数代码:
- 递归处理 AST 节点生成嵌套的
_c(createElement)调用 - 处理指令、事件等特殊属性
- 生成包含静态节点渲染优化的代码结构
function generate(ast) {
const code = ast ? genElement(ast) : '_c("div")'
return new Function(`with(this){return ${code}}`)
}
function genElement(node) {
if (node.staticRoot && !node.staticProcessed) {
return genStatic(node)
}
const children = genChildren(node)
return `_c('${node.tag}',${genData(node)},${children})`
}
核心编译流程
完整的编译流程通过 compileToFunctions 整合:
function compileToFunctions(template) {
const ast = parse(template.trim())
optimize(ast)
const code = generate(ast)
return {
ast,
render: code,
staticRenderFns: cachedStaticRenderFns
}
}
关键设计要点
- 编译器与运行时分离:完整版包含编译器,运行时版依赖预编译
- 分层设计:解析器、优化器、生成器职责分明
- 静态优化:通过编译时分析减少运行时开销
- 平台无关:核心编译逻辑与平台特定的节点操作分离
通过这种设计,Vue 实现了高效的模板到渲染函数的转换过程,为虚拟 DOM 的 patch 过程提供了优化的基础。







