源码分析通常都是从入口开始慢慢分析,这次将直接开始分析核心,然后由内而外找到代码源头。更加符合分析时候的思路。
解析的核心就是parseHTML函数:利用while循环和正则表达式对template的字符串模板逐字符解析。
Vue模板解析的时候对script/style/textarea这个三个标签做了特殊处理。所有,大体上,编译字符串标签分成两类
非script/style/textarea标签
textEnd = html.index("<"),利用textEnd这个变量来区分节点是否为文本节点。
文本节点:
其他元素节点:
1. 注释节点
2. 条件注释节点
3. 标签
4. 结束标签
advance函数:index为当前的解析位置,每次解析完都要截取html字符串,直至html解析完为空字符串,while循环终止
**parseEnd函数:**endTagMatch[1]为当前标签名称,curIndex为闭合标签字符串的其实位置,index为闭合标签字符串的结束位置(advance中已经对index做出了改变)。
利用stack存储解析中的标签,例如模板为
然后调用end函数来生成AST节点。
5. 开始标签
handleStartTag函数:利用attribute/dynamicAttribute正则来解析属性及其值,然后将标签入栈。
另外,由于标签可能是自闭合标签,如
,此类标签是不需要入栈的。
随后,将lastTag更新为此时正在解析的标签。
最后,调用start函数来生成AST节点。
6. 文本元素
解析文本元素的时候要考虑到文本元素中存在<符号。考虑到标签开始/结尾/注释节点/条件注释节点都有<符号,因此在不满足以上条件的正则时,文本会一直解析下去。
最后调用chars函数处理文本节点。
script/style/textarea标签
对于这三个元素,模板解析的时候会把这些元素内的所有内容都当成字符串来处理。并且利用replace函数处理了里面部分字符串,然后调用了chars函数。
最后依然是更新index与html,并处理父元素闭合标签。具体见注释。
html=last
parseEndTag()
利用不传参的parseEndTag函数来清空内部栈。
最后
其实Vue模板编译部分看似很长,其实没有什么东西。
真正的精髓是
1. 书写正确的正则表达式
2. 利用栈结构来保证标签解析正确与否
3. 利用while循环
另外,文章一开始的parseHTML中就有template与options参数,template就是我们书写的模板字符串,options包含了很多,其中就有解析开始标签/结束标签/文本节点时调用的options.start/end/chars,下文将解析这部分内容,分析Vue如何将解析得到的字符转化成AST节点。