Vue的生命週期的詳解

先斬意中人發表於2023-04-28

Vue的生命週期

   Vue的生命週期是每個使用Vue框架的前端人員都需要掌握的知識,以此作為記錄。
   Vue的生命週期就是vue例項從建立到銷燬的全過程,也就是new Vue() 開始就是vue生命週期的開始。Vue 例項有⼀個完整的⽣命週期,也就是從開始建立、初始化資料、編譯模版、掛載Dom -> 渲染、更新 -> 渲染、解除安裝 等⼀系列過程,稱這是Vue的⽣命週期。鉤子函式是Vue生命週期中每個階段對外開放讓程式設計師操作Vue的介面。Vue有8個鉤子函式。

beforeCreate( 建立前 )

這個時候,在例項被完成建立出來,el和data都沒有初始化,不能訪問data、method,一般在這個階段不進行操作。

beforeCreate() {
    console.log('----beforeCreate----')
    console.log(this.msg) //undefined
    console.log(this.$el) //undefined
  },

created( 建立後 )
       這個時候,vue例項中的data、method已被初始化,屬性也被繫結,但是此時還是虛擬dom,真是dom還沒生成,$el 還不可用。這個時候可以呼叫data和method的資料及方法,created鉤子函式是最早可以呼叫data和method的,故一般在此對資料進行初始化。

created() {
    console.log('----created----')
    console.log(this.msg)	//msg
    console.log(this.$el)	//undefined
  },

beforeMount( 掛載前)
  此時模板已經編譯完成,但還沒有被渲染至頁面中(即為虛擬dom載入為真實dom),此時el存在則會顯示el。在這裡可以在渲染前最後一次更改資料的機會,不會觸發其他的鉤子函式,一般可以在這裡做初始資料的獲取。
  當vue例項中,el為掛載目標,未對el進行定義,則this.el顯示undefined,但頁面中存在template也能識別掛載目標,因為template可以被看成佔位符。如果對其進行定義則顯示<div id="app"></div>,故所以,beforeMount讀取不了真實的el,在mounted才能讀取到真實的el,因為el只有渲染完成後才會存在。這裡講的el是真實的el。在真實的el之前存在前,在beforeMount中的其實是頁面中的#app,是掛載的目標。

  beforeMount() {
    console.log('----beforeMount----')
    console.log(this.msg)	//msg
    console.log(this.$el)	//undefined
  },

Mounted( 掛載後)
  此時模板已經被渲染成真實DOM,使用者已經可以看到渲染完成的頁面,頁面的資料也是透過雙向繫結顯示data中的資料。 這例項建立期間的最後一個生命週期函式,當執行完 mounted 就表示,例項已經被完全建立好了,此時,如果沒有其它操作的話,這個例項,就靜靜的躺在我們的記憶體中,一動不動。

mounted() {
    console.log('----mounted----')
    console.log(this.msg)	//msg
    console.log(this.$el)	//<div id="app"><span model="msg"></span></div>
  },

建立Vue例項的示例

<template>
  <div id="app">
    <span :model="msg"></span>
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      msg: 'msg',
    }
  },
  beforeCreate() {
    console.log('----beforeCreate----')
    console.log(this.msg) //msg
    console.log(this.$el) //undefined
  },
  created() {
    console.log('----created----')
    console.log(this.msg)
    console.log(this.$el)
  },
  beforeMount() {
    console.log('----beforeMount----')
    console.log(this.msg)
    console.log(this.$el)
  },
  mounted() {
    console.log('----mounted----')
    console.log(this.msg)
    console.log(this.$el)
  },
}
</script>

 

beforeUpdate(更新前)
  更新前狀態(view層的資料變化前,不是data中的資料改變前),重新渲染之前觸發,然後vue的虛擬dom機制會重新構建虛擬dom與上一次的虛擬dom樹利用diff演算法進行對比之後重新渲染。只有view上面的資料變化才會觸發beforeUpdate和updated,僅屬於data中的資料改變是並不能觸發。

updated(更新後)
資料已經更改完成,dom也重新render完成。

更新例項

<template>
  <div id="app">
    <div style="height:50px"
         ref="spanRef">{{msg}}</div>
    <button @click="clickBtn"></button>
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      msg: 'msg',
    }
  },
  methods: {
    clickBtn() {
      this.msg = 'newMsg'
    },
  },
  beforeUpdate() {
    console.log('----beforeUpdate----')
    console.log(this.$refs.$el)
    console.log(this.msg) //msg
  },
  updated() {
    console.log('----updated----')
    console.log(this.$refs.$el)

    console.log(this.msg) //msg
  },
}
</script>

新增一個按鈕,給按鈕繫結點選事件,點選後更新資料。

  在這裡跟vue圖示有出入,vue圖示中說明在beforeUpdate階段,只有data中的資料改變,而試圖的還未更新,檢視中還是舊的資料,但在示例中,beforeUpdate鉤子函式列印el可看出試圖中的資料已更新。查閱資料後發現,檢視層的資料更新才會觸發beforeUpdate以及updated。如果data中的某資料更新,但這個資料並沒有繫結在檢視層,這個時候就不會觸發鉤子函式。但在思考後發現還是不對,上文所解釋的是,當檢視層所應用的data更新時,觸發鉤子函式。
  這個時候壓力就來到了我這邊,百思不得其姐之後,我突然想到 console.log(this.$refs.$el)這個輸出程式碼,在給beforeUpdate中新增延時程式碼後我頓悟了,console.log(this.$refs.$el)輸出的是資料完成更新時候的el。

this.$el會等到資料更新完成才對el進行輸出。

beforeDestroy(銷燬前)
銷燬前執行($destroy方法被呼叫的時候就會執行),一般在這裡善後:清除計時器、清除非指令繫結的事件等等…’)

destroyed(銷燬後)
銷燬後 (Dom元素存在,只是不再受vue控制),解除安裝watcher,事件監聽,子元件。

相關文章