What is AST? Parsing of AST syntax tree in Vue source code
这篇文章给大家介绍的内容是关于什么是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...
以
<p> 请输入:<input><br> </p>
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不是类似<script>,<style>这样的纯文本标签 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 } } //判断是否处理向下兼容的注释,类似<![if !IE]> //var conditionalComment = /^<!\[/; if (conditionalComment.test(html)) { var conditionalEnd = html.indexOf(']>'); if (conditionalEnd >= 0) { advance(conditionalEnd + 2); continue } } //获取<!DOCTYPE开头的标签内容 // var doctype = /^<!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) { //代码省略 } }</script>
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),右开始标签的位置(end)。本文的例子,程序第一次进入该函数,所以tagName:p,start:0,end:14 match
function 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 <p>在该函数中,对match进行了二次处理,根据标签名、属性生成一个新对象,push到最开始的stack数组中。<br>由于匹配的是起始标签,所以也会以这个标签名结束,此处的lastTag就是p。<br>函数最后调用了parse内部声明的方法start</p><pre class="brush:php;toolbar:false">function 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 ' + "" + ', as they will not be parsed.' ); } // apply pre-transforms for (var i = 0; i <p>对标签名进行校验,同时对属性进行更细致的处理,如v-pre,v-for,v-if等。最后调用processElement(element, options)对当前的树节点元素进行处理,具体如下:</p><pre class="brush:php;toolbar:false"> 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 <p>start()生成element对象,再连接元素的parent和children节点,最后push到栈中,此时栈中第一个元素生成。结构如下:</p><p style="text-align: center;"><span class="img-wrap"><img src="/static/imghw/default1.png" data-src="https://img.php.cn//upload/image/187/717/423/1533181233204676.png" class="lazy" title="1533181233204676.png" alt="What is AST? Parsing of AST syntax tree in Vue source code"></span></p><p>接下来开始第二次循环,html变成了 请输入:<input type="text" v-model="message"></p><p>,因此这次解析的是文字:'请输入',具体代码分析在下一次~~~</p><p class="post-topheader custom- pt0">相关文章推荐:</p><p class="post-topheader custom- pt0"><a href="http://www.php.cn/php-weizijiaocheng-256904.html" target="_blank" class="title">使用PHP-Parser生成<span class="course-color">AST</span>抽象语法树</a></p>
The above is the detailed content of What is AST? Parsing of AST syntax tree in Vue source code. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

When using the Vue framework to develop front-end projects, we will deploy multiple environments when deploying. Often the interface domain names called by development, testing and online environments are different. How can we make the distinction? That is using environment variables and patterns.

Ace is an embeddable code editor written in JavaScript. It matches the functionality and performance of native editors like Sublime, Vim, and TextMate. It can be easily embedded into any web page and JavaScript application. Ace is maintained as the main editor for the Cloud9 IDE and is the successor to the Mozilla Skywriter (Bespin) project.

The difference between componentization and modularization: Modularization is divided from the perspective of code logic; it facilitates code layered development and ensures that the functions of each functional module are consistent. Componentization is planning from the perspective of UI interface; componentization of the front end facilitates the reuse of UI components.

Vue.js has become a very popular framework in front-end development today. As Vue.js continues to evolve, unit testing is becoming more and more important. Today we’ll explore how to write unit tests in Vue.js 3 and provide some best practices and common problems and solutions.

Foreword: In the development of vue3, reactive provides a method to implement responsive data. This is a frequently used API in daily development. In this article, the author will explore its internal operating mechanism.

In Vue.js, developers can use two different syntaxes to create user interfaces: JSX syntax and template syntax. Both syntaxes have their own advantages and disadvantages. Let’s discuss their differences, advantages and disadvantages.

There are two ways to query the current Vue version: 1. In the cmd console, execute the "npm list vue" command to query the version. The output result is the version number information of Vue; 2. Find and open the package.json file in the project and search You can see the version information of vue in the "dependencies" item.

How to handle exceptions in Vue3 dynamic components? The following article will talk about Vue3 dynamic component exception handling methods. I hope it will be helpful to everyone!
