Faster, Higher, Stronger
更快,更高,更强

Vue2.5.16源码解读二:从入口文件进行阅读

接上回,我们确认了一个入口文件src/platforms/web/entry-runtime-with-compiler.js ,将该文件代码折叠如下图所示,方便一览全局:

可以看到这里import Vue from ‘./runtime/index’ 引入了一个Vue ,然后定义了下Vue.prototype.$mount 和Vue.compile ,看Vue源码之前最好是先过一下Vue的官方文档,这里Vue.prototype.$mount 是一个关在Vue原型链上的属性,所以通过new Vue() 创建的Vue的实例都会继承这个$mount 方法,在看这个方法的作用之前,因为看过了官方文档,并且我之前用了两年的Vue了,所以先猜测下这个大概跟Vue组件生命周期里的mounted 钩子可能有关系,可能是这个$mount 方法执行完后就会触发组件生命周期里的mounted 这个钩子里写的程序。现在详细看下相关代码:

const mount = Vue.prototype.$mount
// 返回类型是Component,这个类型下文具体讲,就直译为返回一个组件即可
Vue.prototype.$mount = function (
  // el是可选参数,值是字符串(css选择符)或dom元素(Element)
  el?: string | Element,
  // hydrating也是可选参数,布尔类型,以前用过redux-persist这个库,那里这种名词的意思是是否恢复之前的数据
  hydrating?: boolean
): Component {
  // 如果el是元素则值维持不变,如果el是字符串则赋值为通过document.querySelector(el)匹配到的元素
  el = el && query(el)

  // 下面注释里的istanbul指的是一个叫istanbul的代码覆盖率工具
  /* istanbul ignore if */
  if (el === document.body || el === document.documentElement) {
    process.env.NODE_ENV !== 'production' && warn(
      // 如果元素是body/document.documentElement,且非针对生产环境打包的话,则提示用户不要将Vue绑定到html或body元素上
      `Do not mount Vue to <html> or <body> - mount to normal elements instead.`
    )
    // 返回this
    return this
  }

  // 一个$options属性
  const options = this.$options
  // 如果没有定义render函数,则Vue会按下面这样去定义一个render函数
  // resolve template/el and convert to render function
  if (!options.render) {
    let template = options.template
    if (template) {
      // 如果有模版
      if (typeof template === 'string') {
        if (template.charAt(0) === '#') {
          // 如果template是一个id选择器(以#开头),则将template重新赋值为对应元素的innerHTML
          template = idToTemplate(template)
          /* istanbul ignore if */
          if (process.env.NODE_ENV !== 'production' && !template) {
            // 如果id关联到的innerHTML为空或不存在,则在非生产版本下提示用户
            warn(
              `Template element not found or is empty: ${options.template}`,
              this
            )
          }
        }
      } else if (template.nodeType) {
        // 如果template不是字符串,但是有nodeType属性,则判断template为dom,取其innerHTML作为模版
        template = template.innerHTML
      } else {
        if (process.env.NODE_ENV !== 'production') {
          warn('invalid template option:' + template, this)
        }
        // 返回this
        return this
      }
    } else if (el) {
      // 如果没有模板但是有元素,就取元素的outerHtml或近似等价的东西
      template = getOuterHTML(el)
    }
    if (template) {
      /* istanbul ignore if */
      if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
        // 通过window.performance.mark来标记性能监测点'compile'
        mark('compile')
      }

      // 获得render和staticRenderFns函数,并挂到Vue.property.$options对象上
      const { render, staticRenderFns } = compileToFunctions(template, {
        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) {
        // 通过window.performance.mark标记性能监测点'compile end'
        mark('compile end')
        // 通过window.erformance.measure来测量compile和compile end这两个性能监测点间的用时
        measure(`vue ${this._name} compile`, 'compile', 'compile end')
      }
    }
  }
  // 再次调用mount方法
  return mount.call(this, el, hydrating)
}

好了,这篇文章对入口文件的分析就写到这里,后续我们将以入口文件为线索展开阅读其他部分的代码。打算看一下Vue.compile = compileToFunctions 这里的compileToFunctions 方法,以及import Vue from ‘./runtime/index’ 这里导入的Vue 。

赞(0) 打赏
未经允许不得转载:峰间的云 » Vue2.5.16源码解读二:从入口文件进行阅读

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏