vue 模版编译
vue模板是怎么从template 编译成js代码(最后转换成render函数,生成VS DOM)的,根据官网例子,可以看到从模版编译到js代码的前后转变;Vue Template Explorer
源码解析
vue3源码中的package
目前主要分析的是compiler-core核心模块,从源码compile中;
- template变成JS的过程,主要分为3个步骤
-
-
- baseParse: 词法解析,语法解析,生成vue AST;
-
- transform: vue AST转换成JS AST,转换vue的一些模版语法,做一些节点标记的性能优化
-
- generate: 生成js code(render函数,渲染DOM)
-
baseParse
- 词法解析:tokenizer的模块, tokenizer.parse(currentInput)词法解析;
- template解析成VUE AST;
- AST中各个属性的简介
children: AST子节点的信息;
codegenNode: 描述节点的基本重要信息,比如节点类型等;
components: 是否包括子组件;
directives: 是否包括指令;
filters: 是否包括过滤器;
helpers:helpers函数的set集合,用来生产VSDOM的api;
hoists: 优化左右,用来做静态节点的缓存和提升;
imports: 是否外部导入模块
loc: 代码定位信息
source: 源代码;
transform
对AST进行语义分析, 转换成js AST, 主要对template中的源码的特殊语法和指令进行转换
transform(
ast,
extend({}, resolvedOptions, {
nodeTransforms: [
...nodeTransforms,
...(options.nodeTransforms || []), // user transforms
],
directiveTransforms: extend(
{},
directiveTransforms,
options.directiveTransforms || {}, // user transforms
),
}),
)
- 语法层面包括:if for,slot等等;指令包括on, bind,model等;
- 还会根据每个节点类型打上是否是静态节点的标签,在diff的时候做性能优化;
- 最后生成的JS AST
generate
const result = generate(ast, resolvedOptions);
- result.code就是最后生成的code
import { toDisplayString as _toDisplayString, createElementVNode as _createElementVNode, vModelText as _vModelText, withDirectives as _withDirectives, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"
export function render(_ctx, _cache, $props, $setup, $data, $options) {
return (_openBlock(), _createElementBlock(_Fragment, null, [
_createElementVNode("h1", null, _toDisplayString($setup.msg), 1 /* TEXT */),
_withDirectives(_createElementVNode("input", {
"onUpdate:modelValue": _cache[0] || (_cache[0] = $event => (($setup.msg) = $event))
}, null, 512 /* NEED_PATCH */), [
[_vModelText, $setup.msg]
])
], 64 /* STABLE_FRAGMENT */))
}