美文网首页
Vue源码阅读(二)

Vue源码阅读(二)

作者: 一许青衫一 | 来源:发表于2019-12-29 23:11 被阅读0次

Vue实例


  如果简单了解过些Vue的API的话,肯定会对一下这个特别熟悉,在上一篇里,分析了Vue的核心文件core的index.js构造vue函数执行的流程。

new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})

  那么上面这个则是实例化构造函数,也就是开始使用了,不管是作为框架,还是作为插件,都需要new一下。千呼万唤,我们把它请出来之后,发现点不同的东西,router、filter、store暂时先不表,但是这个#app是个啥东西?翻篇回去,先看Vue的构造函数,this._init(options)是调用的第一个方法,包括传进来的参数options,不过在这之前,还判断了下调用Vue的是不是先new出来的。


image.png

从init方法到Vue初始化做的第一件事


根据注入的文件 找到了 init方法的文件,它是在core/instance/init.js,完整的方法如下:

export function initMixin (Vue: Class<Component>) {
  Vue.prototype._init = function (options?: Object) {
    const vm: Component = this
    // a uid
    vm._uid = uid++

    let startTag, endTag
    /* istanbul ignore if */
    if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
      startTag = `vue-perf-start:${vm._uid}`
      endTag = `vue-perf-end:${vm._uid}`
      mark(startTag)
    }

    // a flag to avoid this being observed
    vm._isVue = true
    // merge options
    if (options && options._isComponent) {
      // optimize internal component instantiation
      // since dynamic options merging is pretty slow, and none of the
      // internal component options needs special treatment.
      initInternalComponent(vm, options)
    } else {
      vm.$options = mergeOptions(
        resolveConstructorOptions(vm.constructor),
        options || {},
        vm
      )
    }
    /* istanbul ignore else */
    if (process.env.NODE_ENV !== 'production') {
      initProxy(vm)
    } else {
      vm._renderProxy = vm
    }
    // expose real self
    vm._self = vm
    initLifecycle(vm)
    initEvents(vm)
    initRender(vm)
    callHook(vm, 'beforeCreate')
    initInjections(vm) // resolve injections before data/props
    initState(vm)
    initProvide(vm) // resolve provide after data/props
    callHook(vm, 'created')

    /* istanbul ignore if */
    if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
      vm._name = formatComponentName(vm, false)
      mark(endTag)
      measure(`vue ${vm._name} init`, startTag, endTag)
    }

    if (vm.$options.el) {
      vm.$mount(vm.$options.el)
    }
  }
}

   一开始是定义了两个属性 _uid 和_isVue。 其中_uid是当前实例的唯一id,而且是递增的实例id 保证不会重复,一般会自动分配,不建议操作,当然如果需要操作的话,可以手动分配。_isVue设置为true,避免监听对象时自身被监听。然后是判断是否定义_isComponent(),这里查了下注释和代码,is_Component = true是指内部的组件实例,而initInternalCompoent()函数是作者对组件内部实例化的优化,一般我们写的代码都会走else的分支,也就是mergeOptions() 这个方法。


image.png

  接下来就遇到了第一个比较重要的点,理解mergeOptions这个方法,他定义在工具类的options这个js文件夹下。首先想到的是为什么要进行策略对象的合并,而且是init的第一步,简单的说,Vue在处理选项的时候,使用了这个策略对象把父子选项进行合并,并将最终的值赋值给实例下的$options,更直白的说就是把vue实例上原有的属性和传入的$option以及继承和构造的所有属性进行递归式的合并,确保一个vue实例是有一个$options.
  先说下这个options,当我们new一个vue的实例时,可以传一些数据,比如上面new的函数那样,从前边看,vue的实例在实例化后会加载很多其他的东西,例如生命周期钩子、render函数等等。而手动传入的这个对象,就叫做options,也是上面vm.$options中传入的第二个参数,关于vm.$options,是一个贯穿整个源码的属性,可以单独拆出来讲,但是为了文章的完整性,先简单说一下,不然后边的这个合并策略对象就会云里雾里。
  等待后面详细梳理一下mergeOptions的执行流程。

总结一下


  总结一下Vue的初始化:Vue的初始化主要就干了这么几件事:合并配置、初始化生命周期、初始化事件和渲染逻辑、初始化data做数据劫持,这种把不同的功能和逻辑部分拆分成一个个单独的模块,使得Vue的核心加载过程一目了然,这种编程思想是十分值得借鉴的。

相关文章

  • Vue源码阅读(二)

    组件化 vue可以使用组件化来开发,在前边介绍_createElement方法时,在对原生的tag时直接创建vno...

  • Vue源码阅读(二)

    Vue实例   如果简单了解过些Vue的API的话,肯定会对一下这个特别熟悉,在上一篇里,分析了Vue的核心文件c...

  • Vue源码学习

    源码地址[https://github.com/vuejs/vue]源码阅读路径 scripts/build.js...

  • Vue早期源码阅读(二)

    Vue.js 早期源码阅读(版本号154861f71d4886251e0057c74f07c786f5262081...

  • 深入Vue - 源码目录及构建过程分析

    摘要: Vue源码阅读第一步。 原文:深入vue - 源码目录及构建过程分析 公众号:前端小苑 Fundebug经...

  • 2020 一起读 vue 源码

    最近在收集一些资料来帮助自己理解和阅读 vue 的源码。在学习和阅读过程中,发现我们读解 vue 源码难度是在于很...

  • Vue 学习笔记

    [TOC] Vue 学习笔记 Vue 源码解析 - 主线流程 Vue 源码解析 - 模板编译 Vue 源码解析 -...

  • Vue 源码解析 - 模板编译

    [TOC] Vue 学习笔记 Vue 源码解析 - 主线流程 Vue 源码解析 - 模板编译 Vue 源码解析 -...

  • Vue 源码解析 - 主线流程

    [TOC] Vue 学习笔记 Vue 源码解析 - 主线流程 Vue 源码解析 - 模板编译 Vue 源码解析 -...

  • Vue 源码解析 - 组件挂载

    [TOC] Vue 学习笔记 Vue 源码解析 - 主线流程 Vue 源码解析 - 模板编译 Vue 源码解析 -...

网友评论

      本文标题:Vue源码阅读(二)

      本文链接:https://www.haomeiwen.com/subject/sgbuoctx.html