模板编译 — 分析模板转译
最后更新于: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',他会在在编译时候进行了转译,也就是将运行解析的过程放到了编译过程中
~~~