Vue源码解析(四)之 $mount 做了什么

$mount 做了什么

  • 前面我们提到过,我们的 demo 在执行完 vm.$mount(vm.$options.el) 就把 hello 渲染到了页面上,那这个过程发生了什么呢
  • 我们先看下entry-runtime-with-compiler.js,其中定义了 $mount 方法
const mount = Vue.prototype.$mount
Vue.prototype.$mount = function (
  el?: string | Element,
  hydrating?: boolean
): Component {
  el = el && query(el)

  if (el === document.body || el === document.documentElement) {
    return this
  }

  const options = this.$options
  if (!options.render) {
    let template = options.template
    if (template) {
      if (typeof template === 'string') {
        if (template.charAt(0) === '#') {
          template = idToTemplate(template)
          if (process.env.NODE_ENV !== 'production' && !template) {
            warn(
              `Template element not found or is empty: ${options.template}`,
              this
            )
          }
        }
      } else if (template.nodeType) {
        template = template.innerHTML
      } else {
        return this
      }
    } else if (el) {
      template = getOuterHTML(el)
    }
    if (template) {

      const { render, staticRenderFns } = compileToFunctions(template, {
        outputSourceRange: process.env.NODE_ENV !== 'production',
        shouldDecodeNewlines,
        shouldDecodeNewlinesForHref,
        delimiters: options.delimiters,
        comments: options.comments
      }, this)
      options.render = render
      options.staticRenderFns = staticRenderFns
    }
  }
  return mount.call(this, el, hydrating)
}
  • 首先它query $options.el,通过 query 函数我们可以发现这一步实际上就是获取真实的DOM元素
export function query (el: string | Element): Element {
  if (typeof el === 'string') {
    const selected = document.querySelector(el)
    if (!selected) {
      return document.createElement('div')
    }
    return selected
  } else {
    return el
  }
}
  • 接着会判断获取的真实 dom元素是否为 body 或 documentElement
  • 接下来会判断 options.render 是否有存在,我们的 demo 里并没有写 render,因此继续看里面的逻辑
  • 没有 render 它会判断 options.template 是否存在,如果不存在template = getOuterHTML(el),即获取 el 的 outerHTML
function getOuterHTML (el: Element): string {
  if (el.outerHTML) {
    return el.outerHTML
  } else {
    const container = document.createElement('div')
    container.appendChild(el.cloneNode(true))
    return container.innerHTML
  }
}
  • 然后通过compileToFunctions将 template 转化为 render 函数,options.render = render

  • 再调用mount.call(this, el, hydrating),这里的 mount 函数是什么呢,在代码第一行里const mount = Vue.prototype.$mount,所以此处我们调用的是之前原型对象上的 $mount 函数,这个函数的做了什么我们会在下一篇中进行分析

调试 demo

  • 执行 $mount 出 debugger


    Vue源码解析(四)之 $mount 做了什么_第1张图片
  • 拿到 template


    Vue源码解析(四)之 $mount 做了什么_第2张图片
  • template 转化为 render 函数


    Vue源码解析(四)之 $mount 做了什么_第3张图片

你可能感兴趣的:(Vue源码解析(四)之 $mount 做了什么)