什么是php的ast结构,什么是AST?Vue源码中AST语法树的解析
这篇文章给大家介绍的内容是关于什么是AST?Vue源码中AST语法树的解析,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。
什么是AST
AST是指抽象语法树(abstract syntax tree),或者语法树(syntax tree),是源代码的抽象语法结构的树状表现形式。Vue在mount过程中,template会被编译成AST语法树。
然后,经过generate(将AST语法树转化成render function字符串的过程)得到render函数,返回VNode。VNode是Vue的虚拟DOM节点,里面包含标签名、子节点、文本等信息,关于VNode的学习来自:https://blog.csdn.net/qq_3626...
以
请输入:
parse()var stack = [];
var preserveWhitespace = options.preserveWhitespace !== false;
var root;
var currentParent;
var inVPre = false;
var inPre = false;
var warned = false;
function warnOnce (msg){
}
function closeElement (element){
}
//调用parseHTML,这里对options的内容省略
parseHTML(template,options);
定义一些变量,root用于存放AST树根节点,currentParent存放当前父元素,stack用来辅助树建立的栈。接着调用parseHTML函数进行转化,传入template和options。
options的结构如下:
parseHTML()
parseHTML内容大纲
last = html;
//确认html不是类似
if (!lastTag || !isPlainTextElement(lastTag)) {
var textEnd = html.indexOf('<');//判断html字符串是否以<开头
if (textEnd === 0) {
// 这里的Comment是Vue定义的正则表达式,判断html是不是注释
//var comment = /^
if (comment.test(html)) {
var commentEnd = html.indexOf('-->');
if (commentEnd >= 0) {
if (options.shouldKeepComment) {
options.comment(html.substring(4, commentEnd));
}
advance(commentEnd + 3);
continue
}
}
//判断是否处理向下兼容的注释,类似
//var conditionalComment = /^
if (conditionalComment.test(html)) {
var conditionalEnd = html.indexOf(']>');
if (conditionalEnd >= 0) {
advance(conditionalEnd + 2);
continue
}
}
//获取/p>
// var doctype = /^^>]+>/i;
var doctypeMatch = html.match(doctype);
if (doctypeMatch) {
advance(doctypeMatch[0].length);
continue
}
//判断此段html是否结束标签
// var endTag = new RegExp(("^<\\/" + qnameCapture + "[^>]*>"));
// var qnameCapture = "((?:" + ncname + "\\:)?" + ncname + ")";
// var ncname = '[a-zA-Z_][\\w\\-\\.]*';
var endTagMatch = html.match(endTag);
if (endTagMatch) {
var curIndex = index;
advance(endTagMatch[0].length);
parseEndTag(endTagMatch[1], curIndex, index);
continue
}
// 匹配开始标签,获取match对象
var startTagMatch = parseStartTag();
if (startTagMatch) {
handleStartTag(startTagMatch);
if (shouldIgnoreFirstNewline(lastTag, html)) {
advance(1);
}
continue
}
var text = (void 0), rest = (void 0), next = (void 0);
if (textEnd >= 0) {
rest = html.slice(textEnd);
while (
!endTag.test(rest) &&
!startTagOpen.test(rest) &&
!comment.test(rest) &&
!conditionalComment.test(rest)
) {
// 处理文本中的<字符
next = rest.indexOf('<', 1);
if (next < 0) { break }
textEnd += next;
rest = html.slice(textEnd);
}
text = html.substring(0, textEnd);
advance(textEnd);
}
if (textEnd < 0) {
text = html;
html = '';
}
if (options.chars && text) {
options.chars(text);
}
} else {
//代码省略
}
if (html === last) {
//代码省略
}
}
parseHTML使用while循环对传进来的html进行解析。首先获取<标签索引var textEnd = html.indexOf('<');如果textEnd为0 说明是标签或者,再用正则匹配是否为注释标签,如果不是,再判断是否为向下兼容放入注释,如(详情见),如果不是,再判断是否已如果不是,再判断当前是否结束标签。var endTagMatch = html.match(endTag); 匹配不到那么就是开始标签,调用parseStartTag()函数解析。
parseStartTag()function parseStartTag () {
var start = html.match(startTagOpen);
if (start) {
var match = {
tagName: start[1],//标签名,本文的例子p
attrs: [],
start: index//0
};//定义match对象
advance(start[0].length);//index=4,html=" id="test">...
var end, attr;
//match对象的attrs
//index=14
while (!(end = html.match(startTagClose)) && (attr = html.match(attribute))) {
advance(attr[0].length);
match.attrs.push(attr);
}
// 在第二次while循环后 end匹配到结束标签 => ['>','']
if (end) {
match.unarySlash = end[1];
advance(end[0].length);
match.end = index;
return match
}
}
}
parseStartTag()构建一个match对象,对象里面包含标签名(tagName),标签属性(attrs),<左开始标签的位置(start),>右开始标签的位置(end)。本文的例子,程序第一次进入该函数,所以tagName:p,start:0,end:14 matchfunction advance (n) {
index += n;
html = html.substring(n);
}
advance函数将局部变量index往后推 并切割字符串。
handleStartTag()function handleStartTag (match) {
var tagName = match.tagName;
var unarySlash = match.unarySlash;
if (expectHTML) {
//段落式元素
if (lastTag === 'p' && isNonPhrasingTag(tagName)) {
parseEndTag(lastTag);
}
// 可以省略闭合标签
if (canBeLeftOpenTag$$1(tagName) && lastTag === tagName) {
parseEndTag(tagName);
}
}
var unary = isUnaryTag$$1(tagName) || !!unarySlash;
var l = match.attrs.length;
var attrs = new Array(l);
//解析html属性值{name:'id',value:'test'}的格式
for (var i = 0; i < l; i++) {
var args = match.attrs[i];
if (IS_REGEX_CAPTURING_BROKEN && args[0].indexOf('""') === -1) {
if (args[3] === '') { delete args[3]; }
if (args[4] === '') { delete args[4]; }
if (args[5] === '') { delete args[5]; }
}
var value = args[3] || args[4] || args[5] || '';
var shouldDecodeNewlines = tagName === 'a' && args[1] === 'href'
? options.shouldDecodeNewlinesForHref
: options.shouldDecodeNewlines;
attrs[i] = {
name: args[1],
// 处理转义字符
value: decodeAttr(value, shouldDecodeNewlines)
};
}
// 将切割出来的字符串转换为AST
if (!unary) {
stack.push({ tag: tagName, lowerCasedTag: tagName.toLowerCase(), attrs: attrs });
//设置结束标签
lastTag = tagName;
}
if (options.start) {
options.start(tagName, attrs, unary, match.start, match.end);
}
}
在该函数中,对match进行了二次处理,根据标签名、属性生成一个新对象,push到最开始的stack数组中。
由于匹配的是起始标签,所以也会以这个标签名结束,此处的lastTag就是p。
函数最后调用了parse内部声明的方法startfunction start (tag, attrs, unary) {
//检查命名空间是否是svg或者math
var ns = (currentParent && currentParent.ns) || platformGetTagNamespace(tag);
// handle IE svg bug
/* istanbul ignore if */
if (isIE && ns === 'svg') {
attrs = guardIESVGBug(attrs);
}
//创建element元素,element其实就是{type: 1,
//tag: "p",
//attrsList: [{name: "id", value: "test"}]],
//attrsMap: makeAttrsMap(attrs), //parent:undefined
//children: []}的一个对象
var element = createASTElement(tag, attrs, currentParent);
if (ns) {
element.ns = ns;
}
//排除script,style标签
if (isForbiddenTag(element) && !isServerRendering()) {
element.forbidden = true;
"development" !== 'production' && warn$2(
'Templates should only be responsible for mapping the state to the ' +
'UI. Avoid placing tags with side-effects in your templates, such as ' +
"<" + tag + ">" + ', as they will not be parsed.'
);
}
// apply pre-transforms
for (var i = 0; i < preTransforms.length; i++) {
//若html里面有v-model等指令,通过preTransforms进行转换
element = preTransforms[i](element, options) || element;
}
if (!inVPre) {
// 判断是否有v-pre属性
processPre(element);
if (element.pre) {
inVPre = true;
}
}
//判断标签名是不是pre
if (platformIsPreTag(element.tag)) {
inPre = true;
}
if (inVPre) {
processRawAttrs(element);
} else if (!element.processed) {
// 处理v-for
processFor(element);
// 处理v-if
processIf(element);
// 处理v-once
processOnce(element);
// element-scope stuff
processElement(element, options);
}
// 树结构的root节点处理
if (!root) {
root = element;
checkRootConstraints(root);
} else if (!stack.length) {
// allow root elements with v-if, v-else-if and v-else
if (root.if && (element.elseif || element.else)) {
checkRootConstraints(element);
addIfCondition(root, {
exp: element.elseif,
block: element
});
} else {
warnOnce(
"Component template should contain exactly one root element. " +
"If you are using v-if on multiple elements, " +
"use v-else-if to chain them instead."
);
}
}
if (currentParent && !element.forbidden) {
if (element.elseif || element.else) {
processIfConditions(element, currentParent);
} else if (element.slotScope) { // scoped slot
currentParent.plain = false;
var name = element.slotTarget || '"default"';(currentParent.scopedSlots || (currentParent.scopedSlots = {}))[name] = element;
} else {
currentParent.children.push(element);
element.parent = currentParent;
}
}
if (!unary) {
currentParent = element;
stack.push(element);
} else {
closeElement(element);
}
}
对标签名进行校验,同时对属性进行更细致的处理,如v-pre,v-for,v-if等。最后调用processElement(element, options)对当前的树节点元素进行处理,具体如下:processKey(element);
// 检测是否是空属性节点
element.plain = !element.key && !element.attrsList.length;
// 处理:ref或v-bind:ref属性
processRef(element);
//处理标签名为slot的情况
processSlot(element);
// 处理is或v-bind:is属性
processComponent(element);
for (var i = 0; i < transforms.length; i++) {
element = transforms[i](element, options) || element;
}
//处理属性
processAttrs(element);
start()生成element对象,再连接元素的parent和children节点,最后push到栈中,此时栈中第一个元素生成。结构如下:
接下来开始第二次循环,html变成了 请输入:
,因此这次解析的是文字:'请输入',具体代码分析在下一次~~~
相关文章推荐:
以上就是什么是AST?Vue源码中AST语法树的解析的详细内容,更多请关注php中文网其它相关文章!
本文原创发布php中文网,转载请注明出处,感谢您的尊重!
什么是php的ast结构,什么是AST?Vue源码中AST语法树的解析相关推荐
- Vue源码解析之Template转化为AST的实现方法
什么是AST 在Vue的mount过程中,template会被编译成AST语法树,AST是指抽象语法树(abstract syntax tree或者缩写为AST),或者语法树(syntax tree) ...
- asp.net摄影网站系统VS开发sqlserver数据库web结构c#编程计算机网页源码项目
一.源码特点 ASP.NET C# 摄影网站系统 是一套完善的web设计管理系统,系统具有完整的源代码和数据库,系统主要采用B/S模式开发.开发环境为vs2010,数据库为sqlser ...
- asp.net毕业生信息管理系统VS开发sqlserver数据库web结构c#编程计算机网页源码项目
一.源码特点 asp.net 毕业生信息管理系统 是一套完善的web设计管理系统,系统具有完整的源代码和数据库,系统主要采用B/S模式开发.开发环境为vs2010,数据库为sqlse ...
- 计算机毕业设计asp.net考勤管理系统VS开发sqlserver数据库web结构c#编程计算机网页源码项目
一.源码特点 ASP.NET C# 考勤管理系统 是一套完善的web设计管理系统,系统具有完整的源代码和数据库,系统主要采用B/S模式开发,开发环境为vs2010,数据库为sqlser ...
- asp.net医院信息管理系统VS开发sqlserver数据库web结构c#编程计算机网页源码项目
一.源码特点 asp.net 医院信息管理系统是一套完善的web设计管理系统,系统具有完整的源代码和数据库,系统主要采用B/S模式开发,开发环境为vs2010,数据库为sqlserve ...
- asp.net网上商城系统VS开发sqlserver数据库web结构c#编程计算机网页源码项目
一.源码特点 asp.net 网上商城系统是一套完善的web设计管理系统,系统具有完整的源代码和数据库,系统主要采用B/S模式开发,开发环境为vs2010,数据库为sqlserver2 ...
- 计算机毕业设计asp.net电脑彩票销售管理系统VS开发sqlserver数据库web结构c#编程计算机网页源码项目
一.源码特点 asp.net 电脑彩票销售管理系统 是一套完善的web设计管理系统,系统具有完整的源代码和数据库,系统主要采用B/S模式开发,开发环境为vs2010,数据库为sqlse ...
- asp.net练车管理系统VS开发sqlserver数据库web结构c#编程计算机网页源码项目
一.源码特点 ASP.NET C# 练车管理系统 是一套完善的web设计管理系统,系统具有完整的源代码和数据库,系统主要采用B/S模式开发,开发环境为vs2010,数据库为sqlser ...
- asp.net小说网系统VS开发物业sqlserver数据库web结构c#编程计算机网页源码项目
一.源码特点 asp.net小说网系统是一套完善的web设计管理系统,系统具有完整的源代码和数据库,系统主要采用B/S模式开发,开发环境为vs2010,数据库为sqlserver200 ...
最新文章
- 第1课第4.4节_Android硬件访问服务编写HAL代码
- 操作系统结构-外核结构
- PC Lint 初学
- pythonexcel汇总_用python汇总excel表格数据-怎样用python遍历表格中的内容
- IPv6 — 与 5G 共荣共生
- 吴涛 :低延迟传输协议和新Codec将成为热点
- SQL学习之去重复查询
- windows和ubuntu双系统设置开机默认系统
- return 输出为空php,thinkphp5 返回json数据的方法---以及返回json为空的原因
- java jvm内存模型_Java(JVM)内存模型– Java中的内存管理
- 带你区分超键,候选键,主键
- 阿里天池—2022江苏气象预测AI算法挑战赛
- 直击人心的数据可视化设计作品
- 微信开发者工具IDE调试webview内嵌H5方式
- 罗杨美慧 20190919-5 代码规范,结对要求
- access阿里云 mysql_access数据库字段最大
- Java多线程编程之读写锁【ReentrantReadWriteLock】
- 网站图片尺寸规格设计指导
- 对英雄联盟比赛预测(一)- 特征分析
- 三菱PLC项目案例学习之自动寻槽铣槽机
热门文章
- Script:Generate A DDL Script For A Table
- 得到节点值的两种方法
- 用JAVA制作小游戏——推箱子(三)
- ubuntu14.04如何安装teamviewer
- 怎么修改SQL Server服务器选项,Analysis Services 实例的 SPN 注册 | Microsoft Docs
- 区块链概念——学习笔记
- nginx配置多个站点的方法
- 印度将推出太阳能光伏制造政策
- maven缺少依赖包,强制更新命令
- Oracle11gR2 RAC+DataGuard安装实施维护2+1_数据库集群容灾视频教程