深刻解析vue的生命週期

一.vue生命週期的解析html

1>什麼是vue生命週期

每一個vue實例在被建立以前都要通過一系列的初始化過程,這個過程就是vue的生命週期。詳細來講,就是Vue實例從開始建立,初始化數據,編譯模板,掛在dom->渲染,更新->渲染,卸載等一系列過程,咱們稱這是vue的生命週期,各個階段有相對應的事件鉤子。vue

2>vue生命週期都有哪些,對應的鉤子函數能夠作什麼
首先,Vue官網的生命週期的圖很清楚明瞭的代表有哪些鉤子函數,而後咱們對應每一個鉤子函數詳細講解一下。

clipboard.png

  • (1)new Vue()

實例化vue對象react

  • (2)init events 和 init cycle

初始化事件和生命週期ios

  • (3)beforeCreate鉤子函數

在實例初始化以後,this指向建立的實例,不能訪問到data,computed,watch,methods上的方法和數據。此時,vue組件對象被建立,可是vue對象的屬性尚未綁定,即沒有值。也就是說,在beforeCreate函數,是在實例初始化以後,數據觀測和event/watcher事件配置以前被調用。axios

beforeCreate() {
    console.log('建立前-掛在', this.$el)
    console.log('建立前-data', this.$data)
  },

打印結果:segmentfault

clipboard.png

實踐場景--經常使用於初始化非響應式變量數組

  • (4)init injections & reactivity

掛在數據(屬性賦值),包括屬性和computed的運算.在beforeCreated和created兩個鉤子函數之間發生。dom

clipboard.png
打印結果:函數

clipboard.png

經過打印結果,發現計算屬性的值在beforeCreated鉤子函數中拿不到,在created鉤子函數中拿獲得,說明計算屬性是在beforeCreated和created這兩個鉤子函數之間進行處理賦值的。優化

  • (5)created函數

實例建立完成,在created鉤子函數這個時期,咱們可以訪問到data,computed,methods上的方法和數據,可是,這會尚未掛在dom。不能訪問到$el,$ref屬性內容未空數組。

created() {
    console.log('建立時--el', this.$el)
    console.log('建立時--data', this.message)
    console.log('建立時-computed', this.a)
    console.log('建立時--methods', this.onClick())
  }

結果:

clipboard.png

實戰場景--經常使用於簡單的axios請求,頁面的初始化。

  • (6)是否有el屬性,和template屬性

clipboard.png

接下來判斷對象上是否有el選項,若是有的話,就繼續向下編譯,若是沒有el選項,就中止編譯,也就意味着中止了生命週期。等到手動綁定調用vm.$mount()完成全局變量$el的綁定。
若是對象有el選項以後,判斷是否有template項,若是有template模板,則將其做爲編譯模板編譯成render函數。若是沒有template模板,則將外部的HTML做爲模板編譯,所以,能夠看出,template中的模板優先級高於outer HTML 的優先級。若是有render函數,則會替換template
所以:優先級關係:render>template>out html

  • (7)beforeMount鉤子函數

在掛載開始以前被調用,beforeMount以前,會找到對應的template,並編譯成render函數。
此時,this.$el上有值,可是數據還沒掛載到頁面上,即此時頁面中的{{}}尚未被替換掉。

beforeMount() {
    console.log('掛在以前調用', this.$el)
  },

打印結果:

clipboard.png

  • (8)mounted鉤子函數

實例掛載到DOM上,此時能夠經過DOM API獲取到DOM節點,$ref屬性能夠訪問。

mounted () {
    console.log('掛在dom節點', this.$el)
  },

打印結果:

clipboard.png

  • (9)beforeupdate鉤子函數

響應式數據更新時調用,發生在虛擬DOM打補丁以前。
組件更新以前執行的函數。
數據更新了,可是,vue(組件)對象對應的dom中的內部(innerHTML)沒有變,因此叫做組件更新前。

beforeUpdate() {
    console.log('組件更新前--數據', this.message)
    console.log('組件更新前--dom', this.$el.innerHTML)
  },

打印結果:

clipboard.png

實戰場景:適合在更新以前訪問現有的DOM,好比手動移除已添加的事件監聽器

  • (10)updated鉤子函數

虛擬 DOM 從新渲染和打補丁以後調用,組件DOM已經更新,可執行依賴於DOM的操做

updated() {
    console.log('組件更新時--數據', this.message)
    console.log('組件更新時--dom', this.$el.innerHTML)
}

打印結果:

clipboard.png

  • (11)beforeDestroy鉤子函數
beforeDestroy() {
    console.log('實例銷燬前', this.$el)
},

實例銷燬以前調用。這一步,實例仍然徹底可用,this仍能獲取到實例

打印結果:
clipboard.png

  • (12)destory鉤子函數

實例銷燬後調用,調用後,Vue 實例指示的全部東西都會解綁定,全部的事件監聽器會被移除,全部的子實例也會被銷燬。

二.父子組件之間生命週期的執行順序
爲了證實一下父子組件之間的生命週期,先看一下頁面的渲染父子組件生命週期時如何進行的

clipboard.png

打印結果:

clipboard.png
根據打印結果,咱們能發現,首先走的是父組件的生命週期,在走完beforeMount以後,就子組件開始走生命週期,直接到子組件掛載dom節點以後,父組件在掛載dom節點。這樣,頁面渲染完畢。
那麼,當數據發生更新的時候,父子組件的beforeUpdate,update的順序是怎麼樣的呢?

噹噹噹,打印結果來了,一目瞭然:會先走父組件的beforeUpdate,而後走子組件的beforeUpdate, updated,只有等子組件更新完畢以後,父組件纔會走updated。更新完畢。

clipboard.png

銷燬的時候,父子組件的銷燬順序是怎樣的呢?
父組件會先走銷燬前的鉤子函數,而後子組件走銷燬前,和銷燬後的鉤子函數,子組件銷燬完畢以後,父組件在走銷燬時的鉤子函數。

clipboard.png

三.混入mixins的生命週期
當組件生命週期與mixins混入的生命週期發生碰撞時,又會擦出什麼樣子的火花呢?

clipboard.png
打印結果:

clipboard.png

clipboard.png

經過打結果,咱們不難發現,當mixins的生命週期與組件的生命週期碰撞的時候,會先走mixins的生命週期,在走組件的生命週期

四.總結
一直想寫一篇關於生命週期的博客,來總結一下,本身在項目中碰見的問題,就是有時候 發現一些問題真的是由於生命週期的掌握不牢固而致使的,雖然已經解決,可是還但願本身能動手去在根據本身的小demo證明一下,生命週期的具體流程。在這裏總結了一個vue實例在被建立前所經歷的一系列的初始化的過程。vue從出生到死亡的整個過程。以及在父子組件中,生命週期是如何走的,還有混入的時候,混入的生命週期與組件的生命週期的執行順序。可能還存在總結不足的地方,後續會繼續優化的。

借鑑:在寫這篇文章的時候,也借鑑了幾篇其餘人的博客,發現寫的很好。給你們推薦一下。
https://juejin.im/entry/5aee8...

https://blog.csdn.net/jiang77...

https://segmentfault.com/a/11...

相關文章
相關標籤/搜索