Vue源碼學習(二)——生命週期

官網對生命週期給出了一個比較完成的流程圖,以下所示:vue

clipboard.png

從圖中咱們能夠看到咱們的Vue建立的過程要通過如下的鉤子函數:數組

beforeCreate => created => beforeMount => mounted
=> beforeUpdate => updated
=> beforeDestroy => destroyed

那麼咱們就從源碼的角度來看一看吧,當咱們new Vue的時候,會執行_init函數ide

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

init函數以下函數

export function initMixin (Vue: Class<Component>) {
  Vue.prototype._init = function (options?: Object) {
    ....
    如下就是進行了生命週期
    vm._self = vm
    // 首先進行初始化生命週期的參數
    initLifecycle(vm)
    // 在初始化事件
    initEvents(vm)
    // 初始化render
    initRender(vm)
    // 開始調用beforeCreate鉤子函數,和圖中的流程圖同樣
    callHook(vm, 'beforeCreate')
    // 以後開始初始化變量等一些數據
    initInjections(vm) // resolve injections before data/props
    initState(vm)
    initProvide(vm) // resolve provide after data/props
    // 開始調用created鉤子函數
    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)
    }
  }
}

以上init函數咱們已經看到了beforeCreate和created,那麼callHook是怎麼調用的鉤子函數呢?this

export function callHook (vm: Component, hook: string) {
  // #7573 disable dep collection when invoking lifecycle hooks
  pushTarget()
  // 從$options裏拿到鉤子函數
  const handlers = vm.$options[hook]
  if (handlers) {
    for (let i = 0, j = handlers.length; i < j; i++) {
      try {
          // 而後再調用
        handlers[i].call(vm)
      } catch (e) {
        handleError(e, vm, `${hook} hook`)
      }
    }
  }
  if (vm._hasHookEvent) {
    vm.$emit('hook:' + hook)
  }
  popTarget()
}

這邊就會有幾個問題:
從vm.$options[hook]中取鉤子函數,那個這個鉤子函數是哪來來的? 爲了拿到的鉤子函數是個數組?咱們平時使用不都是隻是寫個函數嗎?spa

咱們能夠看到在$options是在下面_init中進行合併的prototype

Vue.prototype._init = function(){
    ...
    vm.$options = mergeOptions(
        resolveConstructorOptions(vm.constructor),
        options || {},
        vm
      )
      ...
}

export const LIFECYCLE_HOOKS = [
  'beforeCreate',
  'created',
  'beforeMount',
  'mounted',
  'beforeUpdate',
  'updated',
  'beforeDestroy',
  'destroyed',
  'activated',
  'deactivated',
  'errorCaptured'
]

咱們能夠看到鉤子函數一開始就已經在vue內部已經定義好了,而且還有幾個鉤子函數不是實話化實例的使用執行的。而是對keep-alive組件配合使用的activated,deactivated。以及錯誤拋出鉤子函數errorCaptured
而後再根據這些內部定義的鉤子函數和傳入的參數進行合併code

那麼爲何鉤子函數是數組呢?這個其實很簡單是由於vue內部也須要執行一些函數,顧把函數也放到鉤子函數裏。因此須要數組遍歷。orm

因此這些所謂的鉤子函數就是一個回調函數。生命週期

其他幾個鉤子函數也是在須要調用的時候使用callHook(vm, 'xxx')來執行

若是對您有幫助請點個贊,謝謝!

相關文章
相關標籤/搜索