Vue中父子組件生命週期執行順序回顧

問題背景

在單一組件中,鉤子的執行順序是beforeCreate-> created -> mounted->... ->destroyed,但當父子組件嵌套時,父組件和子組件各擁有各自獨立的鉤子函數,這些父子組件的這些鉤子是如何交融執行,且執行順序又是怎樣的呢?vue

父子組件生命週期執行順序

組件,分別在他們的鉤子函數中打印日誌,觀察執行順序。獲得的結果如圖所示,父組件先建立,而後子組件建立;子組件先掛載,而後父組件掛載。vue-router

父beforeCreate-> 父create -> 子beforeCreate-> 子created -> 子mounted -> 父mounted

複製代碼

子組件掛載完成後,父組件還未掛載。因此組件數據回顯的時候,在父組件mounted中獲取api的數據,子組件的mounted是拿不到的。api

仔細看看父子組件生命週期鉤子的執行順序,會發現created這個鉤子是按照從外內順序執行,因此父子組件傳遞接口數據的解決方案是:緩存

  • 在created中發起請求獲取數據,依次在子組件的created或者mounted中會接收到這個數據。

父子組件生命週期執行順序

加載渲染過程

父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
複製代碼

更新過程

父beforeUpdate->子beforeUpdate->子updated->父updated
複製代碼

銷燬過程

父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
複製代碼

經常使用鉤子簡易版

父create->子created->子mounted->父mounted
複製代碼

補充單一組件鉤子執行順序

activated, deactivated 是組件keep-alive時獨有的鉤子dom

  1. beforeCreate
  2. created
  3. beforeMount
  4. mounted
  5. beforeUpdate
  6. updated
  7. activated
  8. deactivated
  9. beforeDestroy
  10. destroyed
  11. errorCaptured

總結

  • beforeCreate執行時:data和el均未初始化,值爲undefined
  • created執行時:Vue 實例觀察的數據對象data已經配置好,已經能夠獲得data的值,但Vue 實例使用的根 DOM 元素el還未初始化
  • beforeMount執行時:data和el均已經初始化,但此時el並無渲染進數據,el的值爲「虛擬」的元素節點
  • mounted執行時:此時el已經渲染完成並掛載到實例上
  • beforeUpdate和updated觸發時,el中的數據都已經渲染完成,但只有updated鉤子被調用時候,組件dom才被更新。
  • 在created鉤子中能夠對data數據進行操做,這個時候能夠進行數據請求將返回的數據賦給data
  • 在mounted鉤子對掛載的dom進行操做,此時,DOM已經被渲染到頁面上。
  • 雖然updated函數會在數據變化時被觸發,但卻不能準確的判斷是那個屬性值被改變,因此在實際狀況中用computedwatch函數來監聽屬性的變化,並作一些其餘的操做。
  • 全部的生命週期鉤子自動綁定 this 上下文到實例中,因此不能使用箭頭函數來定義一個生命週期方法 (例如 created: () => this.fetchTodos()),會致使this指向父級
  • 在使用vue-router時有時須要使用來緩存組件狀態,這個時候created鉤子就不會被重複調用了,若是咱們的子組件須要在每次加載或切換狀態的時候進行某些操做,可使用activated鉤子觸發。
  • 父子組件的鉤子並不會等待請求返回,請求是異步的,VUE設計也不能由於請求沒有響應而不執行後面的鉤子。因此,咱們必須經過v-if來控制子組件鉤子的執行時機

注意 在父組件傳遞接口的數據給子組件時,必定要在子組件標籤上加上v-if="傳遞的接口數據"

在父組件的created中發請求獲取數據,經過prop傳遞給子組件。子組件在created或者mounted中拿父組件傳遞過來的數據 這樣處理是有問題的。異步

在父組件調用接口傳遞數據給子組件時,接口響應顯然是異步的。這會致使不管你在父組件哪一個鉤子發請求,在子組件哪一個鉤子接收數據。都是取不到的。當子組件的mounted都執行完以後,此時可能父組件的請求才返回數據。會致使,從父組件傳遞給子組件的數據是undefined。函數

解決方法1:

在渲染子組件的時候加上一個條件,data1是父組件調用接口返回的數據。當有數據的時候在去渲染子組件。這樣就會造成自然的阻塞。在父組件的created中的請求返回數據後,纔會執行子組件的created,mounted。最後執行父組件的mounted。fetch

<div class="test">
    <children v-if="data1" :data="data1" ></children>
</div>
複製代碼

解決方法2:

在子組件中 watch 監聽,父組件獲取到值,這個值就會變化,天然是能夠監聽到的this

watch:{
    data:{
      deep:true,
      handler:function(newVal,oldVal) {
        this.$nextTick(() => {
          this.data = newVal
          this.data = newVal.url ? newVal.url : ''
        })
      }
    },
}
複製代碼
相關文章
相關標籤/搜索