模板编译 — 分析模板转译

最后更新于:2022-04-02 08:12:44

>[success] # 代码分析转译模板 ~~~js 1.之前分析过了,即使我们使用的是'模板方式'的$mount,最后也是调用也是'’解析函数'的$mount, 因此在'模板方式'的$mount中会通过'compileToFunctions'将template编译成render函数 /*将template编译成render函数,这里会有render以及staticRenderFns两个返回, 这是vue的编译时优化,static静态不需要在VNode更新时进行patch,优化性能*/ const { render, staticRenderFns } = compileToFunctions(template, { shouldDecodeNewlines, delimiters: options.delimiters }, this) ~~~ >[info] ## 分析template编译成render函数过程 [什么是模板编译](https://vue-js.com/learn-vue/complie/#_1-%E5%89%8D%E8%A8%80) ~~~ 1.引用上面文章里的一段:把用户在标签中写的类似于原生HTML的内容进行编译,把原生 HTML的内容找出来,再把非原生HTML找出来,经过一系列的逻辑处理生成渲染函数,也就是render函数的这 一段过程称之为模板编译过程。 2.Vue会将这些模板转化成AST,抽象语法树,最终得到的 AST 通过一些特定的属性, 能够比较清晰地描述出标签的属性以及依赖关系,说通俗点:一个简单的HTML标签的代码被 转换成了一个JS对象,而这个对象中的属性代表了这个标签中一些关键有效信息。 3.整个解析过程: 3.1.模板解析阶段——解析器——源码路径:src/compiler/parser/index.js; 3.2.优化阶段——优化器——源码路径:src/compiler/optimizer.js; 3.3.代码生成阶段——代码生成器——源码路径:src/compiler/codegen/index.js ~~~ * 解析过程详细分析 [参考Vue源码系列-Vue中文社区](https://vue-js.com/learn-vue/complie/#_1-%E5%89%8D%E8%A8%80) * 引用 掘金小测《剖析 Vue.js 内部运行机制》里面提供AST的样子 ~~~ // 转译前
{{item}}
~~~ ~~~ // 转译后 { /* 标签属性的map,记录了标签上属性 */ 'attrsMap': { ':class': 'c', 'class': 'demo', 'v-if': 'isShow' }, /* 解析得到的:class */ 'classBinding': 'c', /* 标签属性v-if */ 'if': 'isShow', /* v-if的条件 */ 'ifConditions': [ { 'exp': 'isShow' } ], /* 标签属性class */ 'staticClass': 'demo', /* 标签的tag */ 'tag': 'div', /* 子标签数组 */ 'children': [ { 'attrsMap': { 'v-for': "item in sz" }, /* for循环的参数 */ 'alias': "item", /* for循环的对象 */ 'for': 'sz', /* for循环是否已经被处理的标记位 */ 'forProcessed': true, 'tag': 'span', 'children': [ { /* 表达式,_s是一个转字符串的函数 */ 'expression': '_s(item)', 'text': '{{item}}' } ] } ] } ~~~ >[danger] ##### 对vue-loader 说明 ~~~ 1.首先你要知道: vue基于源码构建的有两个版本,一个是runtime only(一个只包含运行时的版本), 另一个是runtime + compiler(一个同时包含编译器和运行时的完整版本)。而两个版本的区别仅 在于后者包含了一个编译器。 2.运行时编译版本,那既然是运行时编译,也就是在项目每次运行都需要一堆正则对我们的html 进行解析,这种解析无疑是耗时的,但是如果你不想这样就要每次开发每次都用render 这个成本也是成倍的 3.为了解决上面的矛盾我们如果在编译阶段利用webpack,loader 插件在编译的过程时候就将这些'.vue' 结尾文件给编译成render 是不是就可以解决问题了,因此我们使vuecli时候内置这种脚手架,默认使用的是 'runtime',由于'runtime'版本是没有'compiler'这个编译器,因此不支持对模板的解析,但又不想写render 便有了'vue-loader',他会在在编译时候进行了转译,也就是将运行解析的过程放到了编译过程中 ~~~
';