从零手写Vue3 中编译原理(二)

一.Vue3 transform实现

对AST语法树进行转化,主要是对AST语法树进行优化操作

export function baseCompile(template) {
    // 1.生成ast语法树
    const ast = baseParse(template);
    // 得到对应的转化方法 元素转化、文本转化...  还有指令转化都应该在这里实现
    const [nodeTransforms] = getBaseTransformPreset()
}
1
2
3
4
5
6
function getBaseTransformPreset() {
    return [
        [
            transformElement,
            transformText
        ],
        // ...指令转化
    ]
}
1
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
function transform(root, options) {
    const context = createTransformContext(root, options);
    traverseNode(root, context)
}
1
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
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

1.元素转化

2.文本转化