vue2 响应式原理 - Vue.prototype.$mount 方法详解

579 阅读1分钟

入口文件

vue.init()调用入口文件$mount方法

入口文件 src\platforms\web\entry-runtime-with-compiler.js

调用 Vue.prototype.$mount

el = el && query(el)

el为创建vue实例传递的选项 首先判断el是否传递 调用 query()方法处理el

export function query (el: string | Element): Element {
  if (typeof el === 'string') {
    const selected = document.querySelector(el)
    if (!selected) {
      process.env.NODE_ENV !== 'production' && warn(
        'Cannot find element: ' + el
      )
      return document.createElement('div')
    }
    return selected
  } else {
    return el
  }
}

query() 首先判断el 是否为字符串 如果不是字符串 就认为el为dom对象 直接返回,如果是字符串 认为el是选择器 找到选择器的dom对象 'selected' 如果找到直接返回 如果没有找到 就判断当前是开发模式还是生产模式 如果不是生产模式会在控制台输出找不到元素 然后创建一个div然后返回

判断el是否为body,html元素 开发环境输出控制台 vue不能挂载到body,html上 只能挂载到普通元素上 然后直接返回vue实例

if (el === document.body || el === document.documentElement) {
    process.env.NODE_ENV !== 'production' && warn(
      `Do not mount Vue to <html> or <body> - mount to normal elements instead.`
    )
    return this
  }

判断是否传递render函数 如果没传递 就获取template 再将template转换成render函数

if (!options.render) {
    let template = options.template
    if (template) {
      if (typeof template === 'string') {
        if (template.charAt(0) === '#') {
          template = idToTemplate(template)
          /* istanbul ignore if */
          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 {
        if (process.env.NODE_ENV !== 'production') {
          warn('invalid template option:' + template, this)
        }
        return this
      }
    } else if (el) {
      template = getOuterHTML(el)
    }
    if (template) {
      /* istanbul ignore if */
      if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
        mark('compile')
      }

      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

      /* istanbul ignore if */
      if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
        mark('compile end')
        measure(`vue ${this._name} compile`, 'compile', 'compile end')
      }
    }
  }

调用mount方法渲染dom

return mount.call(this, el, hydrating)

未完。。。