vue源码之旅-1- new Vue( ) 做了什么事?

源码目录:

     

源码:src / core / instance / index.js 

import { initMixin } from './init'
import { stateMixin } from './state'
import { renderMixin } from './render'
import { eventsMixin } from './events'
import { lifecycleMixin } from './lifecycle'
import { warn } from '../util/index'

function Vue (options) {
  if (process.env.NODE_ENV !== 'production' &&
    !(this instanceof Vue)
  ) {
    warn('Vue is a constructor and should be called with the `new` keyword')
  }
  this._init(options)
}

initMixin(Vue)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue)

export default Vue

从这一段代码可以看出, Vue就是一个普通的函数(构造函数),传入了一个 options 参数, 这个参数是一些用户传入的配置信息, 关键看 this._init(options) 这个方法, 这个方法就是初始化一些Vue的配置, 接着找 这个 _init() 方法, 

src/ core / instance/ init.js    line:15

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)
    }
  }
}

可以看到在函数 Vue 的原型上扩展了一个 _init() 方法, 这里边的代码看这些,可以看出,这个方法,就是初始化Vue 的一些基础内部配置,以及最后的挂载到 指定的 dom 上

这里可以看出初始化了

组件生命周期钩子,自定义事件, 渲染, 以及 state 状态 等

    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')

接着看

src/core /instance/state.js (代码太多就截图了),

这里接着初始了,

数据data, 属性Props,观测 Watch,计算属性Computed, 以及methods方法,混入等

总结:

new Vue() 发生了:

从Vue来说, 就是Vue内部初始化了一些配置,

那么从new 的层面上讲,就是

模拟一个  new 的 实现

function Animal(name) {
  this.name = name
  return {
    name: 'liSi'
  }
}
Animal.prototype.say = function() {
  console.log('Miao')
}
function myNew() {
  // 取出第一个参数, 剩余的arguments 就是其他的参数
  let constructor = [].shift.call(arguments)
  // 不要使用 Object.create(null) 创建的对象, 因为没有原型链 __proto__
  let obj = {} // 返回的结果
  obj.__proto__ = constructor.prototype // 继承原型上的方法
  let result = constructor.apply(obj, arguments) // 改变this 指向 ,把剩余的参数传给它
  // 判断如果是一个 引用类型, 则直接返回这个引用类型的数据
  // 即判断是不是 Object 的实例
  return result instanceof Object ? result : obj
}
let animal = myNew(Animal, '猫')
console.log(animal) // {name: "liSi"}
发布了63 篇原创文章 · 获赞 100 · 访问量 31万+

猜你喜欢

转载自blog.csdn.net/qq_36407748/article/details/105138691