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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章