Vue3
中编译原理(二)
从零手写一.Vue3 transform实现
对AST语法树进行转化,主要是对AST语法树进行优化操作
export function baseCompile(template) {
// 1.生成ast语法树
const ast = baseParse(template);
// 得到对应的转化方法 元素转化、文本转化... 还有指令转化都应该在这里实现
const [nodeTransforms] = getBaseTransformPreset()
}
1
2
3
4
5
6
2
3
4
5
6
function getBaseTransformPreset() {
return [
[
transformElement,
transformText
],
// ...指令转化
]
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
开始进行转化,会先创建转化上下文,之后遍历ast树
function createTransformContext(root, { nodeTransforms }) {
const context = { // 存着一些配置和信息
root,
currentNode: root,
nodeTransforms,
helpers:new Set(),
helper(name){
context.helpers.add(name);
return name;
}
}
return context;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
function transform(root, options) {
const context = createTransformContext(root, options);
traverseNode(root, context)
}
1
2
3
4
2
3
4
深度遍历节点,调用transform函数
function traverseNode(node, context) {
context.currentNode = node;
const { nodeTransforms } = context;
const exitFns: any = [];
for (let i = 0; i < nodeTransforms.length; i++) {
const onExit = nodeTransforms[i](node, context);
if (onExit) {
exitFns.push(onExit)
}
}
switch (node.type) {
case NodeTypes.ROOT: // 最外层
case NodeTypes.ElEMENT: // 元素
traverseChildren(node, context);
break;
}
// 执行退出方法时
context.currentNode = node;
let i = exitFns.length;
while (i--) {
exitFns[i]()
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function traverseChildren(parent, context) {
for (let i = 0; i < parent.children.length; i++) {
const child = parent.children[i];
traverseNode(child, context); // 递归遍历子节点
}
}
1
2
3
4
5
6
2
3
4
5
6