Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vue2 中 template 转换成 ast 过程简介 #4

Open
buppt opened this issue Jun 13, 2020 · 0 comments
Open

vue2 中 template 转换成 ast 过程简介 #4

buppt opened this issue Jun 13, 2020 · 0 comments

Comments

@buppt
Copy link
Owner

buppt commented Jun 13, 2020

这篇文章主要简单介绍 template 转换成 ast 的过程,也就是 vue 中 parse 的过程。

假设 template 模版为

const template = `<div>
    <div style='color: red'>{{count}}</div>
    <button @click="addCount">addCount</button>
</div>`

首先要了解一下 html parser,vue 中的 parseHTML 是从 simplehtmlparser 修改来的,simplehtmlparser​ 代码链接:http://erik.eae.net/simplehtmlparser/simplehtmlparser.js

parseHTML 过程其实就是从前向后的字符串匹配过程。html parser 的主要思想如下,从前向后匹配出 html 标签名称、属性、文本节点内容、注释等等,触发对应的回调函数,其中 s 是输入的字符串模版,contentHandler 是匹配到内容后执行的回调函数。

function parseHTML(s, contentHandler) {
    while (s.length > 0) {
        // Comment
        if (s.substring(0, 4) == "<!--") {
            index = s.indexOf("-->");
            if (index != -1) {
                contentHandler.comment(s.substring(4, index));
                s = s.substring(index + 3);
                treatAsChars = false;
            } else {
                treatAsChars = true;
            }
        }
        // end tag
        else if (s.substring(0, 2) == "</") {
            contentHandler.end(sTagName);
        }
        // start tag
        else if (s.charAt(0) == "<") {
            var attrs = parseAttributes(sTagName, sRest);
            contentHandler.start(sTagName, attrs);
        }
        if (treatAsChars) {
            index = s.indexOf("<");
            if (index == -1) {
                contentHandler.chars(s);
                s = "";
            } else {
                contentHandler.chars(s.substring(0, index));
                s = s.substring(index);
            }
        }
    }
}

我们将刚才的模版输入到这个函数中

const handler = {
    start: function (sTagName, oAttrs) {
        console.log('start', sTagName, oAttrs)
    },
    end: function (sTagName) {
        console.log('end', sTagName)
    },
    chars: function (s) {
        console.log('chars', s)
    },
    comment: function (s) {
        console.log('comment', s)
    }
};
parseHTML(template, handler);

这样就可以按顺序匹配到开始标签、标签属性、元素中文本节点、结束标签​。​

start div []
chars 

start div [ { name: 'style', value: 'color: red' } ]
chars {{count}}
end div
chars 

start button [ { name: '@click', value: 'addCount' } ]
chars addCount
end button
chars 

end div

最后如何生成 AST,就是一道栈相关的算法题啦,大家可以自己尝试一下。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant