Press "Enter" to skip to content

#yyds干货盘点#——如何通俗理解AST抽象语法树(一)

本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢.

在用vue开发项目的过程中,生命周期里有mounted这一环节,mounted方法是把
template会被编译成AST语法树。说AST之前,要说一说编译器,编译器的作用是把源代码编译成目标代码,源代码是什幺呢? 用vue开发的话,源代码就是.vue文件,目标代码就是可被浏览器执行的.js文件。编译器的概念很多,大致上分为词法分析、语法分析(句法分析)、类型检查/推导,代码优化,代码生成…等等,编译器是大学要学的一门课。如果只讲编译器是很枯燥的,大部分人看了一部分后就看不下去了,通过vue代码能够直观的理解编译器的工作方式,vue的编译器和大部分编译器一样,大致也分为三个阶段,即:词法分析 -> 句法分析 -> 代码生成。

 

在词法分析阶段vue会把字符串模板解析成一个个的令牌(token),该令牌将用于句法分析阶段,在句法分析阶段会根据令牌生成一棵AST,最后再根据该 AST生成最终的渲染函数,这样就完成了代码的生成。vue模板的解析基本分两步:

 

1、在mounted阶段,执行compile方法将template里的内容转化成html。

 

2、compile过程分三步:parse,optimize,generate

 

今天先分析一下compile方法是如何来解析template模板的,也就是compile的parse阶段。

 

​compile 的作用是解析模板,生成渲染模板的 render:

 

比如说这样的模板:

 

<div>
   <span></span>
</div>

 

经过compile之后,编译成render函数

 

_c('div', [_c('span')])

 

而render的作用是生成如下的模板节点:

 

{    
    tag: "div",    
    children:[{        
        tag: "span",        
        text: undefined
    }]
}

 


parse基础解读

对模板进行解析,生成AST,意思就是通过json键值对形式,把template用树这样的数据结构表示出来。

 

比如上面的例子:

 

<div>
   <span></span>
</div>

 

生成的 AST 是这样,所有模板中出现的数据,你都可以在 AST 中找到

 

{    
    tag: "div",      
    children:[{        
        tag: "span",        
        children: [],        
        attrsMap: {class: "list"}
    }]
}

 

AST就是用数据的方式来描述事物。

 

parse详细分析

 


parse 是 渲染三巨头的老大,
其作用是把 template 字符串模板,转换成 AST,关于AST的概念,我也查了很多资料,主要是以树状结构描述语法结构,什幺意思呢?

 

比如:

 

<div>
    <span>123</span>
</div>

 

这是一个带有表达式的模板,转化起来相当简单。

 

AST={
  tag:'div', 
  type: 1,
  children:[{
    tag: 'span',
    type: 1,
    children:[{
      type:3,
      text: '123'
    }]
  }]
}

 

这个很简单吧,type是描述节点的类型,
它有三个可取值,分别是 1、2、3,分别代表的含义是:

1:代表当前节点类型为标签,例如:div、span、li

 

2:包含字面量表达式的文本节点,例如: {{info}}

 

3:普通文本节点或注释节点,例如:”周笔畅是男的”

 

parse源码分析

 

function parse(template) {    
    var stack = []; // 缓存模板中解析的每个节点的 ast
    var root;   // 根节点,是 ast
    var currentParent; // 当前解析的标签的父节点
    /**
    * parseHTML 处理 template 匹配标签,再传入 start,end,chars 等方法
    **/    
    parseHTML(template, {        
        start: (..被抽出,在后面)
        end: (..被抽出,在后面), // 为 起始标签 开启闭合节点
        chars: (..被抽出,在后面) // 文字节点    
    });    
    return root
}

 

parse 接收 template 字符串,使用 parseHTML 这个函数在 template 中匹配标签

 

并传入 start,end,chars 三个函数 供 parseHTML 处理标签等内容。

 

这篇文章先写到这里,下一篇文章再给大家看一下parseHTML究竟是怎幺回事,铺开来讲,AST是一个庞大的知识库,没有足够的知识、精力和体力是难以完成的,编写不易,请大家多多点赞。

Be First to Comment

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注