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的创建原理我之后再写文章单独分析。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐