Vue3 的编译模块包含4个目录:
compiler-core // 编译核心
Compiler-DOM // 浏览器相关
Compiler-sfc // 单文件组件
Compiler-SSR // 服务端渲染
其中,compiler-core 模块是Vue编译的核心模块,与平台无关。其余三个基于 compiler-core,适用于不同的平台。
Vue 的编译分为三个阶段,即 解析(Parse)、转换(Transform)和代码生成(Codegen)。
Parse 阶段将模板字符串转换为语法抽象树 AST。Transform 阶段对 AST 做一些转换处理。Codegen 阶段根据 AST 生成相应的渲染函数字符串。
Parse 阶段
分析模板字符串时,Vue 可分为两种情况:以< 开头的字符串,和不是以 < 开头的字符串。
不是以 < 开头的字符串有两种情况:文本节点或者插入表达式 { {exp}}。
使用 < 将字符串的开头分为以下几种情况:
- 元素开始标签 <div>
- 元素结束标签 </div>
- 注释节点 <!-- 123 -->
- 文件声明 <!DOCTYPE html>
用伪代码表示,近似过程如下:
while (s.length) {
if (startsWith(s, '{
{')) { // 如果开始为 '{
{'
node = parseInterpolation(context, mode)
} else if (s[0] === '<') { // 元素开始标签
if (s[1] === '!') {
if (startsWith(s, '<!--')) { // 注释节点
node = parseComment(context)
} else if (startsWith(s, '<!DOCTYPE')) { //文档语句
node = parseBogusComment(context)
}
} else if (s[1] === '/') { // 结束标签
parseTag(context, TagType.End, parent)
} else if (/[a-z]/i.test(s[1])) { // 开始标签名
node = parseElement(context, ancestors)
}
} else { // 普通文本节点
node = parseText(context, mode)
}
}
相对应的几个函数如下:
parseChildren()
,入口函数parseInterpolation()
,分析双花插值表达式parseComment()
,解析注释parseBogusComment()
,分析文件声明parseTag()
,分析标签parseElement()
,分析元素节点,它将在内部执行parseTag()
parseText()
,分析普通文本parseAttribute()
,分析属性
当标签、文本、注释等每个节点生成相应的AST节点时,Vue 将截断解析的字符串。
字符串被截断是使用 AdvanceBy(context,numberOfCharacters)函数,context 是字符串的上下文对象,