这篇文章主要简单介绍 template 转换成 ast 的过程,也就是 vue 中 parse 的过程。
假设 template 模版为
const template = ` {{count}} addCount`
首先要了解一下 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 divchars
start button [ { name: '@click', value: 'addCount' } ]chars addCountend buttonchars
end div
最后如何生成 AST,就是一道栈相关的算法题啦,大家可以自己尝试一下。
领取专属 10元无门槛券
私享最新 技术干货