前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Vue中的模板编译原理

Vue中的模板编译原理

作者头像
刘亦枫
发布2020-03-19 17:35:10
1.5K0
发布2020-03-19 17:35:10
举报

先看下模板到真正用户看到的界面过程中经历了什么:

模板———>模板编译——>渲染函数——>vnode——>用于界面

vue.js提供了模板语法,允许我们声明式的描述状态和DOM之间的绑定关系。

将模板编译为渲染函数,就是模板编译要做的事,模板编译可以分为三个阶段:

1.将模板解析为AST(抽象语法树)—— 解析器。 2.遍历AST标记静态节点 —— 优化器。 3.使用AST生成渲染函数 —— 代码生成器)。

其实 AST 和 Vnode 类似,都是使用JavaScript对象来描述节点。更准确的说,一个用对象来描述的节点树就是 AST。

在这里插入图片描述
在这里插入图片描述

解析器

代码语言:javascript
复制
<div>
  <p>{{name}}</p>
</div>

上面一个简单 的模版转换成element AST树形结构后是这样的:

代码语言:javascript
复制
{
  tag: "div"
  type: 1,
  staticRoot: false,
  static: false,
  plain: true,
  parent: undefined,
  attrsList: [],
  attrsMap: {},
  children: [
      {
      tag: "p"
      type: 1,
      staticRoot: false,
      static: false,
      plain: true,
      parent: {tag: "div", ...},
      attrsList: [],
      attrsMap: {},
      children: [{
          type: 2,
          text: "{{name}}",
          static: false,
          expression: "_s(name)"
      }]
    }
  ]
}

解析器的原理不是特别难,主要就是两部分内容,一部分是 截取 字符串,一部分是对截取之后的字符串做解析。每截取一段标签的开头就 push 到 stack中,解析到标签的结束就 pop 出来,当所有的字符串都截没了也就解析完了。

优化器 优化器的目的就是找出那些静态节点并打上标记,而静态节点指的是DOM不需要发生变化的节点,也就是里面都是静态标签和静态文本。

代码语言:javascript
复制
< p>我是静态节点,我不需要发生变化</ p>

标记静态节点有两个好处: 一、每次重新渲染的时候不需要为静态节点创建新节点,也就是静态节点的解析器不需要重新创建 二、在Virtual DOM中patching的过程可以被跳过

优化器的实现原理主要分两步: 一、用递归的方式将静态节点添加static属性,用来标识是不是静态节点 二、标记所有静态根节点(子节点全是静态节点就是静态根节点)

整体逻辑其实就是递归 AST 这颗树,然后将 静态节点和 静态根节点找到并打上标记。

代码生成器 代码生成器的作用是使用element ASTs生成render函数代码字符串。 使用本文开头举的例子中的模版生成后的AST来生成render后是这样的:

代码语言:javascript
复制
{
  render: `with(this){return _c('div',[_c('p',[_v(_s(name))])])}`
}

格式化后是这样的:

代码语言:javascript
复制
with(this){
  return _c(
    'div',
    [
      _c(
        'p',
        [
          _v(_s(name))
        ]
      )
    ]
  )
}

生成后的代码字符串中看到了有几个函数调用_c、_v、_s。 _c对应的是createElement,它的作用是创建一个元素。 1.第一个参数是一个HTML标签名 2.第二个参数是元素上使用的属性所对应的数据对象,可选项 3.第三个参数是children _v的意思是创建一个文本节点。 _s是返回参数中的字符串。 代码生成器的总体逻辑其实就是使用element ASTs去递归,然后拼出这样的_c(‘div’,[_c(‘p’,[_v(_s(name))])]) 字符串。

原理

解析器(parser)的原理是一小段一小段的去截取字符串,然后维护一个 stack 用来保存DOM深度,每截取到一段标签的开始就 push 到 stack 中,当所有字符串都截取完之后也就解析出了一个完整的 AST。

优化器(optimizer)的原理是用递归的方式将所有节点打标记,表示是否是一个 静态节点,然后再次递归一遍把 静态根节点 也标记出来。

代码生成器(code generator)的原理也是通过递归去拼一个函数执行代码的字符串,递归的过程根据不同的节点类型调用不同的生成方法,如果发现是一颗元素节点就拼一个 _c(tagName, data, children) 的函数调用字符串,然后 data 和 children 也是使用 AST 中的属性去拼字符串。

如果 children 中还有 children 则递归去拼。

最后拼出一个完整的 render 函数代码。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 原理
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档