美文网首页
Vue模版编译原理

Vue模版编译原理

作者: A郑家庆 | 来源:发表于2019-10-18 11:07 被阅读0次

关于Vue编译原理这块的整体逻辑主要分为三步:

  • 第一步将模版字符串转换成element ASTs(解析器)
  • 第二步是对AST进行静态节点标记,主要用来做虚拟DOM的渲染优化(优化器)
  • 第三步是使用element ASTs生成render函数代码字符串(代码生成器)

解析器

<div>
  <p>{{name}}</p>
</div>

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

{
  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)"
      }]
    }
  ]
}

我们可以看到上面的dom被解析成了解析器,它的原理主要是两部分内容,一部分是截取字符串,一部分是对截取的字符串做解析。

优化器

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

标记静态节点有两个好处:
  • 一、每次重新渲染的时候不需要为静态节点创建新节点,也就是静态节点的解析器不需要重新创建
  • 二、在Virtual DOM中patching的过程可以被跳过
优化器的实现原理主要分两步:
  • 一、用递归的方式将静态节点添加static属性,用来标识是不是静态节点
  • 二、标记所有静态根节点(子节点全是静态节点就是静态根节点)

代码生成器

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

{
  render: `with(this){return _c('div',[_c('p',[_v(_s(name))])])}`
}

格式化后是这样的:

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))])]) 字符串。

总结

本篇文章我们说了 vue 对模板编译的整体流程分为三个部分:解析器(parser),优化器(optimizer)和代码生成器(code generator)。
解析器(parser)的作用是将 模板字符串 转换成 element ASTs。
优化器(optimizer)的作用是找出那些静态节点和静态根节点并打上标记。
代码生成器(code generator)的作用是使用 element ASTs 生成 render函数代码(generate render function code from element ASTs)。

用一张图来表示:


image.png

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

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

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

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

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

问题

一、请问在模板编译的阶段,是不是就会对每个组件所使用的data或者computed值进行访问,从而创建新的Watcher进行订阅,然后对应的属性的dep就会收集这些watcher,从而实现更新的?
答:不是的,模板编译只是会把模板编译成渲染函数,只有在渲染函数被执行的时候才会对数据进行访问,而渲染函数是在watche实例中执行的,所以渲染函数中所使用到的所有数据,都会被同一个Watcher监听,当这些状态发生变化时,会通知这个Watcher,这个Watcher会触发VirtualDOM对组件进行渲染。一个组件的模板会被编译成一个渲染函数。每个组件有一个Watcher用来监听模板中所使用到的数据、当这些数据发生变化时,通过VirtualDOM进行更新组件的视图

相关文章

  • Vue模版编译原理

    关于Vue编译原理这块的整体逻辑主要分为三步: 第一步将模版字符串转换成element ASTs(解析器) 第二步...

  • 6 Vue渲染页面 html模版、template模版、rend

    Vue渲染页面可使用html模版、template模版、render渲染函数;渲染过程的底层原理:模版[strin...

  • vue 编译/双向绑定

    vue编译过程是怎样的 首先编译是因为vue写的模版语句html根本不 识别,我们通过编译的过程,可以进行依赖收集...

  • 编译(一)入口

    回忆之编译入口 编译,其实就是vue对模版指令和内置组件的处理。 编译我们最终执行的是compileToFunct...

  • Vue render 以及createElement 解析

    Vue中的template 里面使用的模版是HTML语法组件的页面,在Vue中都会被编译成render函数,Vue...

  • Vue原理

    vue原理相关 Vue核心概念 vue实例化 虚拟dom 模板编译 数据绑定(响应式) 组件化 MVVM mode...

  • 企业级VUE视频教程——爱创课堂前端培训

    第1天 Vue 2.0 1、vue简介 2、体验vue 3、数据绑定的实现原理 4、webpack编译 5、数据丢...

  • 深入浅出 - vue变化侦测原理

    深入浅出 - vue变化侦测原理 关于vue的内部原理其实有很多个重要的部分,变化侦测,模板编译,virtualD...

  • Vue源码05-mount

    我们在各种初始化都完成的情况下开始Vue挂载 mount函数 模版编译createCompiler parse函数...

  • 实现一个简易的vue

    1./compiler ⽬目录是编译模版; 2./core ⽬目录是 Vue.js 的核⼼心(也是后⾯面的重点);...

网友评论

      本文标题:Vue模版编译原理

      本文链接:https://www.haomeiwen.com/subject/ihdppctx.html