vue 生命周期的詳解


一.vue生命周期的解析

> 1>什么是vue生命周期

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

> 2>vue生命周期都有哪些,對應的鈎子函數可以做什么**

首先,Vue官網的生命周期的圖很清楚明了的表明有哪些鈎子函數,然后我們對應每個鈎子函數詳細講解一下。

> (1)new Vue()

實例化vue對象

> (2)init events 和 init cycle

初始化事件和生命周期

> (3)beforeCreate鈎子函數

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

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

打印結果:

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

> (4)init injections & reactivity
掛在數據(屬性賦值),包括屬性和computed的運算.在beforeCreated和created兩個鈎子函數之間發生。


打印結果:

通過打印結果,發現計算屬性的值在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())
}

結果:

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

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

接下來判斷對象上是否有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)
},

打印結果:

> (8)mounted鈎子函數

實例掛載到DOM上,此時可以通過DOM API獲取到DOM節點,$ref屬性可以訪問。

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

打印結果:

>  (9)beforeupdate鈎子函數

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

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

打印結果:

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

> (10)updated鈎子函數

虛擬 DOM 重新渲染和打補丁之后調用,組件DOM已經更新,可執行依賴於DOM的操作

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

打印結果:

> -(11)beforeDestroy鈎子函數

beforeDestroy() {
console.log('實例銷毀前', this.$el)
},

實例銷毀之前調用。這一步,實例仍然完全可用,this仍能獲取到實例

打印結果:

> (12)destory鈎子函數

實例銷毀后調用,調用后,Vue 實例指示的所有東西都會解綁定,所有的事件監聽器會被移除,所有的子實例也會被銷毀。

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

打印結果:


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

當當當,打印結果來了,一目了然:會先走父組件的beforeUpdate,然后走子組件的beforeUpdate, updated,只有等子組件更新完畢之后,父組件才會走updated。更新完畢

銷毀的時候,父子組件的銷毀順序是怎樣的呢?
父組件會先走銷毀前的鈎子函數,然后子組件走銷毀前,和銷毀后的鈎子函數,子組件銷毀完畢之后,父組件在走銷毀時的鈎子函數。

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

https://segmentfault.com/img/bVbwob8?w=1666&h=953
打印結果:

通過打結果,我們不難發現,當mixins的生命周期與組件的生命周期碰撞的時候,**會先走mixins的生命周期,在走組件的生命周期**。

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

借鑒:在寫這篇文章的時候,也借鑒了幾篇其他人的博客,發現寫的很好。給大家推薦一下。
https://juejin.im/entry/5aee8fbb518825671952308c

https://blog.csdn.net/jiang7701037/article/details/83118665

https://segmentfault.com/a/1190000011381906

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM