返回

走进Vue中的template转换世界:逐行源码解析与剖析

前端

揭秘Vue中template的转化(附源码解析及注释)

您是否曾好奇Vue中template是如何编译成渲染函数的?让我们开启一场源码之旅,逐行解析Vue中template的转化过程,揭开它背后的奥秘。

还记得之前的《手拉手带你过一遍vue部分源码》吗?在那里,我们已经知道,在src/platform/web/entry-runtime-with-compiler.js重写原型的$mount方法时,已经将template转换为render函数了,接下来,我们从这个地方作为入口。

// src/platform/web/entry-runtime-with-compiler.js
mountComponent(vm, el) {
  // 省略其他代码
  const options = this.$options
  if (!options.render) {
    if (options.template) {
      if (process.env.NODE_ENV !== 'production') {
        mountWithTemplate(vm, el)
      } else {
        compileAndMountWithTemplate(vm, el, true)
      }
    } else if (vm.$options.el || vm.$options.attachToDocument) {
      vm.$mount(vm.$options.el || document.createElement('div'))
    }
  }
}

我们发现,当template存在时,Vue会调用mountWithTemplate或compileAndMountWithTemplate方法。前者在开发模式下使用,后者在生产模式下使用。现在,我们深入研究这两个方法。

// src/platform/web/entry-runtime-with-compiler.js
mountWithTemplate(vm, el) {
  const template = vm.$options.template
  if (process.env.NODE_ENV !== 'production') {
    vm.$el = el
    if (Vue.compile) {
      const res = Vue.compile(template)
      // 将模板编译为渲染函数
      vm.$options.render = res.render
      vm.$options.staticRenderFns = res.staticRenderFns
    }
  }
  // 省略其他代码
}

在mountWithTemplate方法中,我们首先获取template选项。然后,如果处于开发模式,我们使用Vue.compile将template编译为渲染函数。编译结果存储在vm.options.render和vm.options.staticRenderFns中。

现在,我们进入compile方法,看看如何将template编译为渲染函数。

// src/compiler/index.js
compile(template, options) {
  const ast = parse(template.trim(), options)
  const code = generate(ast, options)
  const render = new Function(`with(this) { return ${code} }`)
  return {
    render,
    staticRenderFns
  }
}

在compile方法中,我们首先使用parse方法将template解析为抽象语法树(AST)。然后,使用generate方法将AST编译为JavaScript代码。最后,我们将这段代码作为一个函数来执行,这样就可以得到渲染函数。

至此,我们已经完成了template到渲染函数的编译过程的分析。希望这能帮助您更好地理解Vue是如何工作的。如果您有更多问题,欢迎随时提问。