AST
语法树
遍历我们需要遍历ast
语法树,访问树中节点进行语法树的转化
function transformElement(node){
console.log('元素处理',node)
}
function transformText(node){
console.log('文本处理',node)
}
function transformExpression(node){
console.log('表达式')
}
function traverseNode(node,context){
context.currentNode = node;
const transforms = context.nodeTransforms;
for(let i = 0; i < transforms.length;i++){
transforms[i](node,context); // 调用转化方法进行转化
if(!context.currentNode) return
}
switch(node.type){
case NodeTypes.ELEMENT:
case NodeTypes.ROOT:
for(let i = 0; i < node.children.length;i++){
context.parent = node;
traverseNode(node.children[i],context);
}
}
}
function createTransformContext(root){
const context = {
currentNode:root, // 当前转化节点
parent:null, // 当前转化节点的父节点
nodeTransforms:[ // 转化方法
transformElement,
transformText,
transformExpression
],
helpers: new Map(), // 创建帮助映射表,记录调用方法次数
helper(name){
const count = context.helpers.get(name) || 0;
context.helpers.set(name,count+1)
}
}
return context
}
function transform(root){
// 创建转化的上下文, 记录转化方法及当前转化节点
let context = createTransformContext(root)
// 递归遍历
traverseNode(root,context)
}
export function compile(template){
const ast = baseParse(template);
transform(ast);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
退出函数
表达式不需要退出函数,直接处理即可。元素需要在遍历完所有子节点在进行处理
function transformExpression(node){
if(node.type == NodeTypes.INTERPOLATION){
console.log('表达式')
}
}
function transformElement(node){
if(node.type === NodeTypes.ELEMENT ){
return function postTransformElement(){ // 元素处理的退出函数
// 如果这个元素
console.log('元素',node)
}
}
}
function transformText(node){
if(node.type === NodeTypes.ELEMENT || node.type === NodeTypes.ROOT){
return ()=>{
console.log('元素/root',node)
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function traverseNode(node,context){
// ...
for(let i = 0; i < transforms.length;i++){
let onExit = transforms[i](node,context); // 调用转化方法进行转化
if(onExit){
exitsFns.push(onExit)
}
if(!context.currentNode) return
}
// ...
// 最终context.currentNode 是最里面的
context.currentNode = node; // 修正currentNode;
let i = exitsFns.length
while (i--) {
exitsFns[i]()
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
本周更新完毕。。。。。。。
← 模板转化AST语法树 异步组件实现原理 →