vue编译原理之vue-template-compiler

Posted 前端精髓

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue编译原理之vue-template-compiler相关的知识,希望对你有一定的参考价值。

vue-template-compiler是编译vue模板的包,传入模板返回AST抽象语法树。

const compiler = require('vue-template-compiler')

const val = compiler.compile('<span class="active" :total="count">666</span>')

输出结果如下:

const res = {
  ast: {
    type: 1,
    tag: 'span',
    attrsList: [ { name: 'total', value: 'count' } ],
    attrsMap: { class: 'active', ':total': 'count' },
    rawAttrsMap: {},
    parent: undefined,
    children: [ { type: 3, text: 666, static: true } ],
    plain: false,
    staticClass: '"active"',
    hasBindings: true,
    attrs: [ { name: 'total', value: 'count', dynamic: false } ],
    static: false,
    staticRoot: false
  },
  render: `with(this){return _c('span',{staticClass:"active",attrs:{"total":count}},[_v("666")])}`,
  staticRenderFns: [],
  errors: [],
  tips: []
}

可以看到对象中有ast属性和render函数,其实ast是为了生成render函数用的。

with (this) {
  return _c(
    'span',
    { staticClass: "active", attrs: { "total": count } },
    [_v("666")]
  )
}

render函数回调用很多的函数,如果 _c,_v 那么这些都来自哪里呢?

其实是渲染时候用的的辅助函数,源码路径 https://github.com/vuejs/vue/blob/dev/src/core/instance/render-helpers/index.js

export function installRenderHelpers (target: any) {
 target._o = markOnce
 target._n = toNumber
 target._s = toString
 target._l = renderList
 target._t = renderSlot
 target._q = looseEqual
 target._i = looseIndexOf
 target._m = renderStatic
 target._f = resolveFilter
 target._k = checkKeyCodes
 target._b = bindObjectProps
 target._v = createTextVNode
 target._e = createEmptyVNode
 target._u = resolveScopedSlots
 target._g = bindObjectListeners
 target._d = bindDynamicKeys
 target._p = prependModifier
}

可是上面没有没有_c,我们继续寻找源码可以发现在 initRender 这里,路径 https://github.com/vuejs/vue/blob/dev/src/core/instance/render.js

vm._c = (a, b, c, d) => createElement(vm, a, b, c, d, false)

createElement 就是创建虚拟节点 VNode。路径 https://github.com/vuejs/vue/blob/dev/src/core/vdom/create-element.js

VNode 可以在Vue实例上查看。

<body>
  <span id="app" class="active" :total="count">666</span>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>

  <script>
    var app = new Vue({
      el: '#app',
      data: {
        count: 666
      }
    })
    console.log(app)
  </script>
</body>

总结:vue在渲染阶段会把模板编译为AST,然后根据AST生成render函数,底层通过调用render函数会生成VNode创建虚拟DOM。

具体VNode的创建原理我之后再写文章单独分析。

以上是关于vue编译原理之vue-template-compiler的主要内容,如果未能解决你的问题,请参考以下文章

Vue原理Compile - 源码版 之 从新建实例到 compile结束的主要流程

[Vue源码]一起来学Vue模板编译原理-Template生成AST

VUE中如何动态编译js

[Vue源码]一起来学Vue模板编译原理-AST生成Render字符串

Vue原理-模板编译

前端技能树,面试复习第 45 天—— Vue 基础 | 模版编译原理 | mixin | use 原理 | 源码解析