- A+
前言
在之前的 通过debug搞清楚.vue文件怎么变成.js文件 文章中我们讲过了vue文件是如何编译成js文件,通过那篇文章我们知道了,template编译为render函数底层就是调用了@vue/compiler-sfc
包暴露出来的compileTemplate
函数。由于文章篇幅有限,我们没有去深入探索compileTemplate
函数是如何将template模块编译为render
函数,在这篇文章中我们来了解一下。
@vue
下面的几个包
先来介绍一下本文中涉及到vue下的几个包,分别是:@vue/compiler-sfc
、@vue/compiler-dom
、@vue/compiler-core
。
-
@vue/compiler-sfc
:用于编译vue的SFC文件,这个包依赖vue下的其他包,比如@vue/compiler-dom
和@vue/compiler-core
。这个包一般是给vue-loader 和 @vitejs/plugin-vue使用的。 -
@vue/compiler-dom
:这个包专注于浏览器端的编译,处理浏览器dom相关的逻辑都在这里面。 -
@vue/compiler-core
:从名字你也能看出来这个包是vue编译部分的核心,提供了通用的编译逻辑,不管是浏览器端还是服务端编译最终都会走到这个包里面来。
先来看个流程图
先来看一下我画的template模块编译为render
函数这一过程的流程图,让你对整个流程有个大概的印象,后面的内容看着就不费劲了。如下图:
从上面的流程图可以看到整个流程可以分为7步:
-
执行
@vue/compiler-sfc
包的compileTemplate
函数,里面会调用同一个包的doCompileTemplate
函数。 -
执行
@vue/compiler-sfc
包的doCompileTemplate
函数,里面会调用@vue/compiler-dom
包中的compile
函数。 -
执行
@vue/compiler-dom
包中的compile
函数,里面会对options
进行了扩展,塞了一些处理dom的转换函数进去。分别塞到了options.nodeTransforms
数组和options.directiveTransforms
对象中。然后以扩展后的options
去调用@vue/compiler-core
包的baseCompile
函数。 -
执行
@vue/compiler-core
包的baseCompile
函数,在这个函数中主要分为4部分。第一部分为检查传入的source是不是html字符串,如果是就调用同一个包下的baseParse
函数生成模版AST抽象语法树
。否则就直接使用传入的模版AST抽象语法树
。此时node节点中还有v-for
、v-model
等指令。这里的模版AST抽象语法树
结构和template模块中的代码结构是一模一样的,所以说模版AST抽象语法树
就是对template模块中的结构进行描述。 -
第二部分为执行
getBaseTransformPreset
函数拿到@vue/compiler-core
包中内置的nodeTransforms
和directiveTransforms
转换函数。 -
第三部分为将传入的
options.nodeTransforms
、options.directiveTransforms
分别和本地的nodeTransforms
、directiveTransforms
进行合并得到一堆新的转换函数,和模版AST抽象语法树
一起传入到transform
函数中执行,就会得到转换后的javascript AST抽象语法树
。在这一过程中v-for
、v-model
等指令已经被转换函数给处理了。得到的javascript AST抽象语法树
的结构和将要生成的render
函数的结构是一模一样的,所以说javascript AST抽象语法树
就是对render
函数的结构进行描述。 -
第四部分为由于已经拿到了和render函数的结构一模一样的
javascript AST抽象语法树
,只需要在generate
函数中遍历javascript AST抽象语法树
进行字符串拼接就可以得到render
函数了。
关注