1. 程式人生 > >人人都能懂的Vue原始碼系列(八)—initLifecycle

人人都能懂的Vue原始碼系列(八)—initLifecycle

initLifeCycle方法用來初始化一些生命週期相關的屬性,以及為parent,child等屬性賦值,來看原始碼。

export function initLifecycle (vm: Component) {
  const options = vm.$options
  // locate first non-abstract parent
  let parent = options.parent
  if (parent && !options.abstract) {
    while (parent.$options.abstract && parent.$parent) {
      parent = parent.$parent
    }
    parent.$children.push(vm)
  }
  vm.$parent = parent
  vm.$root = parent ? parent.$root : vm

  vm.$children = []
  vm.$refs = {}

  vm._watcher = null
  vm._inactive = null
  vm._directInactive = false
  vm._isMounted = false
  vm._isDestroyed = false
  vm._isBeingDestroyed = false
}

一行一行分析

const options = vm.$options

把mergeOptions後的options賦值給options變數。

// locate first non-abstract parent
  let parent = options.parent
  if (parent && !options.abstract) {
    while (parent.$options.abstract && parent.$parent) {
      parent = parent.$parent
    }
    parent.$children.push(vm)
  }

我們注意到,vue作者對這段程式碼提供了一行註釋

locate first non-abstract parent

定位第一個"非抽象"的父元件,注意非抽象這三個字。什麼是非抽象呢?最初自己也很疑惑,最後在vue文件中找到了答案。

抽象元件的定義如上圖所示,注意這句話,不會出現在父元件鏈中。明白了這點我們再去看上面的程式碼就不會那麼迷糊了。

let parent = options.parent
if (parent && !options.abstract) {
    ... 
}

當前vm例項有父例項parent,則賦值給parent變數。如果父例項存在,且該例項不是抽象元件。則執行下面程式碼

while (parent.$options.abstract && parent.$parent) {
  parent = parent.$parent
}
parent.$children.push(vm)

注意while迴圈內的條件parent.$options.abstract && parent.$parent,如果父例項parent是抽象元件,則繼續找parent上的parent。直到找到非抽象元件為止。之後把當前vm例項push到定位的第一個非抽象parent的$children屬性上。這樣我們就說完了怎麼找vm的parent屬性。 之後我們回到initLifecycle繼續往下看

  vm.$parent = parent
  vm.$root = parent ? parent.$root : vm

  vm.$children = []
  vm.$refs = {}
  vm._watcher = null
  vm._inactive = null
  vm._directInactive = false
  vm._isMounted = false
  vm._isDestroyed = false
  vm._isBeingDestroyed = false

這些程式碼都是為vm一些屬性賦值。這些屬性的作用如下表。

名稱 說明
指定已建立的例項之父例項,在兩者之間建立父子關係。子例項可以用 this.$parent 訪問父例項,子例項被推入父例項的 $children 陣列中。
$root 當前元件樹的根 Vue 例項。如果當前例項沒有父例項,此例項將會是其自己。
當前例項的直接子元件。需要注意 $children 並不保證順序,也不是響應式的。
$refs 一個物件,持有已註冊過 ref 的所有子元件。
元件例項相應的 watcher 例項物件。
_inactive 表示keep-alive中元件狀態,如被啟用,該值為false,反之為true。
_directInactive 也是表示keep-alive中元件狀態的屬性。
_isMounted 當前例項是否完成掛載(對應生命週期圖示中的mounted)。
_isDestroyed 當前例項是否已經被銷燬(對應生命週期圖示中的destroyed)。
_isBeingDestroyed 當前例項是否正在被銷燬,還沒有銷燬完成(介於生命週期圖示中deforeDestroy和destroyed之間)。

initLifecycle方法的邏輯比較簡單,主要對vue例項一些屬性進行賦值。所以這裡就不畫流程圖來進行說明了。下篇文章我們主要講initEvents方法,敬請期待。