前言
在前面的几篇文章中,我们把vue3的编译原理进行了详细分析,从template
转换成AST
到优化AST
,再到通过优化过的AST
生成渲染函数,每一步都缺一不可,可以说是一环扣一环,但这都是理想状态下的情况,那么今天的这篇文章我们就说一点实际的情况t,假设我们有这样子的一个template
,
<h1>hello Vue3</h1>
转换成AST补充
转换的第一步自然是将template
转换成AST
,它会先去走parseChildren
函数,根据不同的规则将template
中的层层节点转换成AST
。
在模板中,先会交给parseElement
进行处理,但是由于里面还有文本节点,在处理完开始标记<h1>
之后还会再次调用parseChildren
中去处理文本,最后由parseTag
处理结束标签,最后转换的结果如下,里面有一个children
属性,存储的h1
标签里的内容。
其他的转换也是类似的流程也是差不多的,基本都是大同小异,比较需要注意的就是attribute
的转换。
AST
语义分析补充
语义分析的主要用途是为了能够生成更好的渲染函数,举个例子,比如v-if
,只转换成AST
树的话,它们只会是以对象的形式存在,那么在v-if
和v-else
同时存在的话,就不能表达出逻辑性,所以在transform
阶段会把他们处理成可以表示逻辑性的对象。
// 转换前大体表示:
{
type: NodeTypes.DIRECTIVE,
name: dirName,
exp: value && {
type: NodeTypes.SIMPLE_EXPRESSION,
content: value.content,
constType: ConstantTypes.NOT_CONSTANT,
},
arg,
modifiers,
}
// 转换后大体表示:
{
consequent,
alternate: {
consequent,
alternate: {
consequent
},
},
}
在转换后的对象中我们可以清楚的明白它们之间的关系和逻辑性,每个对象中都有一个属性alternate
作为当前条件不成立时的候选(else
除外)。在生成渲染函数的时候就可以通过这样的对象嵌套关系去生成代码。
生成渲染函数补充
这一部分是根据前面transform
转换后的AST去生成代码,这里提供十几个方法用来转换将不同的类型的AST对象转换成代码(服务端渲染还提供了五个,客户端渲染提供了十五个),在生成代码的过程中,这些方法是会互相调用,有时还会进行递归,并且在转换的过程中采用的是深度优先的原则。
至于具体生成代码的方法,如果大家感兴趣的话可以自己到代码仓库中去查看,这些生成代码的方法都有一个同一的,就是在最后都会将自己生成的代码拼接到上下文对象中的Code
属性中,到最后会将它变成Function
。
总结
编译原理作为Vue中重要的一部分,有着十分重要的作用,它是Vue运转的开始,一切的源头,并且编译原理的运用的地方十分广泛,比如ES6转换成ES3这些,统统都是用到了编译原理,虽然内部的实现不一样,但是它们都是异曲同工,都是为了将一种东西转换成另外一种东西,学会了编译原理我们可以得到很多东西,比如其中的算法、思想等等,这些东西都可以是我们提升。
最后,希望各路大佬能够指导和补充,谢谢。