关于vue的内部原理其实有很多个重要的部分,变化侦测,模板编译,virtualDOM,整体运行流程等。
之前写过一篇《深入浅出 - vue变化侦测原理》 讲了关于变化侦测的实现原理。
那今天主要把 模板编译这部分的实现原理单独拿出来讲一讲。
本文我可能不会在文章中说太多细节部分的处理,我会把 vue 对模板编译这部分的整体原理讲清楚,主要是让读者读完文章后对模板编译的整体实现原理有一个清晰的思路和理解。
关于 Vue 编译原理这块的整体逻辑主要分三个部分,也可以说是分三步,这三个部分是有前后关系的:
第一步是将 模板字符串 转换成 element ASTs(解析器)
第二步是对 AST 进行静态节点标记,主要用来做虚拟DOM的渲染优化(优化器)
第三步是 使用 element ASTs 生成 render 函数代码字符串(代码生成器)
解析器
解析器主要干的事是将 模板字符串 转换成 element ASTs,例如:
< div> < p>{{name}}</ p></ div>
上面这样一个简单的 模板 转换成 element AST 后是这样的:
{ tag :"div"type :1, staticRoot :false, static :false, plain :true, parent :undefined, attrsList :[], attrsMap :{}, children :[ { tag :"p"type :1, staticRoot :false, static :false, plain :true, parent :{tag :"div", ...}, attrsList :[], attrsMap :{}, children :[{ type :2, text :"{{name}}", static :false, expression :"_s(name)"}] } ]}
我们先用这个简单的例子来说明这个解析器的内部究竟发生了什么。
这段模板字符串会扔到 while 中去循环,然后 一段一段的截取,把截取到的 每一小段字符串进行解析,直到最后截没了,也就解析完了。
上面这个简单的模板截取的过程是这样的:
< div> < p>{{name}}</ p></ div> < p>{{name}}</ p></ div> < p>{{name}}</ p></ div> {{name}}</ p></ div> </ p></ div> </ div> </ div>
那是根据什么截的呢?换句话说截取字符串有什么规则么?
当然有
只要判断模板字符串是不是以 < 开头我们就可以知道我们接下来要截取的这一小段字符串是 标签 还是 文本。
举个