参数

el

  • 类型string | Element
  • 限制:只在用 new 创建实例时生效。
  • 详细
    提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标。可以是 CSS 选择器,也可以是一个 HTMLElement 实例。
    在实例挂载之后,元素可以用 vm.$el 访问。
    如果在实例化时存在这个选项,实例将立即进入编译过程,否则,需要显式调用 vm.$mount() 手动开启编译。
    提供的元素只能作为挂载点。不同于 Vue 1.x,所有的挂载元素会被 Vue 生成的 DOM 替换。因此不推荐挂载 root 实例到 <html> 或者 <body> 上。
    如果 render 函数和 template 属性都不存在,挂载 DOM 元素的 HTML 会被提取出来用作模板,此时,必须使用 Runtime + Compiler 构建的 Vue 库。

    template

  • 类型string

  • 详细
    一个字符串模板作为 Vue 实例的标识使用。模板将会 替换 挂载的元素。挂载元素的内容都将被忽略,除非模板的内容有分发插槽。
    如果值以 # 开始,则它将被用作选择符,并使用匹配元素的 innerHTML 作为模板。常用的技巧是用 <script type="x-template"> 包含模板。
    出于安全考虑,你应该只使用你信任的 Vue 模板。避免使用其他人生成的内容作为你的模板。
    如果 Vue 选项中包含渲染函数,该模板将被忽略。

    render

  • 类型(createElement: () => VNode) => VNode

  • 详细
    字符串模板的代替方案,允许你发挥 JavaScript 最大的编程能力。该渲染函数接收一个 createElement 方法作为第一个参数用来创建 VNode
    如果组件是一个函数组件,渲染函数还会接收一个额外的 context 参数,为没有实例的函数组件提供上下文信息。
    Vue 选项中的 render 函数若存在,则 Vue 构造函数不会从 template 选项或通过 el 选项指定的挂载元素中提取出的 HTML 模板编译渲染函数。

对不同构建版本的解释

  • 完整版:同时包含编译器和运行时的版本。
  • 编译器:用来将模板字符串编译成为 JavaScript 渲染函数的代码。
  • 运行时:用来创建 Vue 实例、渲染并处理虚拟 DOM 等的代码。基本上就是除去编译器的其它一切。

源码入口文件

完整版(编译器+运行时) 编译器 运行时
entry-runtime-with-compiler.js entry-compiler.js entry-runtime.js

区别

运行时(entry-runtime.js)

  1. Vue.prototype.$mount = function (
  2. el?: string | Element,
  3. hydrating?: boolean
  4. ): Component {
  5. el = el && inBrowser ? query(el) : undefined
  6. return mountComponent(this, el, hydrating)
  7. }

完整版(entry-runtime-with-compiler.js)

  1. const idToTemplate = cached(id => {
  2. const el = query(id)
  3. return el && el.innerHTML
  4. })
  5. /**
  6. * Get outerHTML of elements, taking care
  7. * of SVG elements in IE as well.
  8. */
  9. function getOuterHTML (el: Element): string {
  10. // 从注释来看,svg是没有outerHTML的,
  11. // 想要获取html字符串要做兼容
  12. if (el.outerHTML) {
  13. return el.outerHTML
  14. } else {
  15. const container = document.createElement('div')
  16. container.appendChild(el.cloneNode(true))
  17. return container.innerHTML
  18. }
  19. }
  20. const mount = Vue.prototype.$mount
  21. Vue.prototype.$mount = function (
  22. el?: string | Element,
  23. hydrating?: boolean
  24. ): Component {
  25. el = el && query(el)
  26. /* istanbul ignore if */
  27. if (el === document.body || el === document.documentElement) {
  28. // el 不能为body和html
  29. process.env.NODE_ENV !== 'production' && warn(
  30. `Do not mount Vue to <html> or <body> - mount to normal elements instead.`
  31. )
  32. return this
  33. }
  34. const options = this.$options
  35. // resolve template/el and convert to render function
  36. if (!options.render) {
  37. // 没有render函数,如果 Vue 选项中包含渲染函数,该模板将被忽略。
  38. let template = options.template
  39. if (template) {
  40. // 使用了模版语法
  41. if (typeof template === 'string') {
  42. if (template.charAt(0) === '#') {
  43. // 如果值以 # 开始,则它将被用作选择符,并使用匹配元素的 innerHTML 作为模板。
  44. template = idToTemplate(template)
  45. /* istanbul ignore if */
  46. if (process.env.NODE_ENV !== 'production' && !template) {
  47. warn(
  48. `Template element not found or is empty: ${options.template}`,
  49. this
  50. )
  51. }
  52. }
  53. } else if (template.nodeType) {
  54. // 判断这是一段html
  55. template = template.innerHTML
  56. } else {
  57. if (process.env.NODE_ENV !== 'production') {
  58. warn('invalid template option:' + template, this)
  59. }
  60. return this
  61. }
  62. } else if (el) {
  63. // 使用了el的情况
  64. template = getOuterHTML(el)
  65. }
  66. if (template) {
  67. /* istanbul ignore if */
  68. if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
  69. mark('compile')
  70. }
  71. const { render, staticRenderFns } = compileToFunctions(template, {
  72. outputSourceRange: process.env.NODE_ENV !== 'production',
  73. shouldDecodeNewlines,
  74. shouldDecodeNewlinesForHref,
  75. delimiters: options.delimiters,
  76. comments: options.comments
  77. }, this)
  78. // 用compile方法,将template转换成render
  79. options.render = render
  80. options.staticRenderFns = staticRenderFns
  81. /* istanbul ignore if */
  82. if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
  83. mark('compile end')
  84. measure(`vue ${this._name} compile`, 'compile', 'compile end')
  85. }
  86. }
  87. }
  88. return mount.call(this, el, hydrating)
  89. }

从源码来看,完整版多了针对template的处理,使用compile方法将template转换成了render函数。