【Vue2.x 源码学习】第十四篇 - 生成 ast 语法树 - 模板解析
一,前言
上篇,主要介绍了生成 ast 语法树-正则说明部分,涉及以下几个点:
简要说明了 HTML模板的解析方式
对模板解析相关正则说明和测试
本篇,生成 ast 语法树-代码实现
二,模板解析
模板解析的方式:对模板不停截取,直至全部解析完毕,可以使用 while 循环
上篇说到,标签还是文本,要看内容开头的第一个字符是否为尖角号 < :
如果是尖角号,说明是标签;
如果不是尖角号,说明是文本
// src/compiler/index.js#parserHTML
function parserHTML(html) {
while(html){
// 解析标签or文本,看第一个字符是否为尖角号 <
let index = html.indexOf('<');
if(index == 0){
console.log("是标签")
} else{
console.log("是文本")
}
}
}

1,parseStartTag 解析开始标签
包含尖叫号 < 的情况,有可能是开始标签
所以当为标签时,先使用正则匹配开始标签;如果没有匹配成功,再使用结束标签进行匹配
parseStartTag方法:匹配开始标签,返回匹配结果
备注:匹配结果的索引 1 可以得到标签名,属性后续解析
// src/compiler/index.js#parserHTML
function parserHTML(html) {
/**
* 匹配开始标签,返回匹配结果
*/
function parseStartTag() {
// 匹配开始标签,开始标签名为索引 1
const start = html.match(startTagOpen);
// 构造匹配结果,包含标签名和属性
const match = {
tagName:start[1],
attrs:[]
}
console.log("match结果:" + match)
}
// 对模板不停截取,直至全部解析完毕
while (html) {
// 解析标签和文本(看开头是否为<)
let index = html.indexOf('<');
if (index == 0) {
console.log("解析 html:" + html + ",结果:是标签")
// 如果是标签,继续解析开始标签和属性
const startTagMatch = parseStartTag();// 匹配开始标签,返回匹配结果
if (startTagMatch) { // 匹配到开始标签
continue; // 如果是开始标签,无需执行下面逻辑,继续下次 while 解析后续内容
}
// 没有匹配到开始标签,此时有可能为结束标签
调试标签 match 结果:

上边开始标签解析完成后,标签将被截掉:
{{message}}
id=app>{{message}}
为了实现对已经匹配到标签进行截取,
需要 advance 方法:前进,即截取至当前已解析位置
// src/compiler/index.js#parserHTML
function parserHTML(html) {
/**
* 截取字符串
* @param {*} len 截取长度
*/
function advance(len){
html = html.substring(len);
}
/**
* 匹配开始标签,返回匹配结果
*/
function parseStartTag() {
// 匹配开始标签,开始标签名为索引 1
const start = html.match(startTagOpen);
// 构造匹配结果,包含标签名和属性
const match = {
tagName:start[1],
attrs:[]
}
console.log("match 结果:" + match)
// 截取匹配到的结果
advance(start[0].length)
console.log("截取后的 html:" + html)
}
...
}
调试查看截取后的html:

2,解析开始标签中的属性
id="app">{{message}}