Vue2的template编译

164 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第26天,点击查看活动详情

本文来聊聊Vue2的template编译。

$mount

首先可以看到,在$mount方法中,编译template模板时,先判断是否有render函数,render不存在时才会将template进行compileToFunctions得到render以及staticRenderFns,而render函数存在则会优先使用render。

而其中,可以看到当template存在的时候取template,不存在的时候取el的outerHTML。

因此,可以得出,优先级: render>template>el。不过不管哪种形式都会以render函数的形式参与挂载,render是一个用函数封装好的with语句。render函数在运行后会返回VNode节点,最终供页面的渲染以及在update的时候patch。

image.png

image.png

template编译流程

由于不同平台对Vue的编译过程是不一样的,即编译阶段的配置选项会不同,但是尤大又希望每都可以传入相同的配置选项,这才导致了源码的编译实现相对复杂。

按照源码的指示,我们从compileToFunctions逐级查找其根源。可以看到:首先createCompilerCreator在传递了一个baseCompile函数作为参数后,返回了一个编译器的生成器:createCompiler。有了createCompiler,当将编译配置选项baseOptions传入后,这个编译器生成器便创建生成一个指定环境指定配置下的编译器,返回compileToFunctionscompilecompile是一个编译器,它会将传入的template转换成对应的AST、render函数以及staticRenderFns函数。而compileToFunctions则是带缓存的编译器,同时staticRenderFns以及render函数会被转换成Funtion对象

createCompilerCreator、createCompiler

createCompilerCreator函数的主要作用是利用偏函数的思想将baseCompile这一基础的编译方法缓存,并返回一个编程器生成器,当执行var ref$1 = createCompiler(baseOptions);时,createCompiler会将内部定义的compilecompileToFunctions返回。

因为不同平台有一些不同的options,所以createCompiler会根据平台区分传入一个baseOptions,会与compile本身传入的options合并得到最终的finalOptions。

image.png

image.png

compileToFunctions

我们可以发现,compileToFunctions利用了闭包的概念,会有一个functionCompileCache对象作为缓存器。在进入compileToFunctions以后,会先检查缓存中是否有已经编译好的结果,如果有结果则直接从缓存中读取。这样做防止每次同样的模板都要进行重复的编译工作。如果判断为不使用缓存的编译结果后,会执行compile方法。

image.png

compile

compile主要做了两件事,一件是合并option:将用户传递的编译配置和系统自带的编译配置选项合并,另一件是baseCompile,进行模板template的编译。执行完compile会返回一个对象,如下baseCompile的代码可以看到,包括:AST抽象语法树,render是最终生成的with语句,staticRenderFns是以数组形式存在的静态render。

image.png

baseCompile

baseCompile是真正执行编译功能的地方。baseCompile会将模板template进行parse会用正则等方式解析template模板中的指令、class、style等数据,得到一个AST抽象语法树,再通过optimize做一些优化(主要作用是标记static静态节点),最后通过generate将AST转化为render以及staticRenderFns字符串。

image.png