在 Vue 所使用到的整個生命週期方法,可以想像成是一齣戲要上演,哪一個主角需要在哪個時候上場、哪個配角需要在哪個時刻退場,都需要有邏輯才可以讓故事產生連貫性與流暢。
Vue 的生命週期方法雖然共有八個,但並不是每個都需要用到,就像在戲裡,有些橋段不出現、配角不出現也不會影響整齣性的故事性。
把 Vue 的生命週期分為三個大階段會比較容易理解:第一階段的「初始化顯示」、第二階段「更新狀態顯示」、第三階段「死亡、銷毀 Vue 實例」,每個階段都有對應的生命週期 callback 方法,這些生命週期的方法也稱為「生命週期鉤子」掛載在不同時期。 Vue 的生命週期比 React 還要複雜一些。
為了避免 this
的混淆,這些生命週期的方法都是回調方法(callback),所以最好一律都寫成箭頭函式,讓 this
直接指向父級,也就是 vue 實例本身。
Vue 的生命週期各階段都做了什麼?
0. 創建 Vue 的實例
當我們創建好一個 Vue 的實例,就會馬上進入下一個階段beforeCreate()
。
1. 初始化顯示階段
beforeCreate() 實例創建前
- 準備工作:觀察初始化(Observe Data)、初始化事件(Init Events)
- 這個階段實例的 data、methods 是讀不到的
created() 實例創建後
- 這個階段已經完成了資料觀察初始化(data observer),屬性和方法的運算, watch/event 事件回調。mount 掛載階段還沒開始,$el 屬性目前不可見,資料並沒有在 DOM 元素上進行渲染。
beforeMount() 在掛載開始之前被調用
相關的 render 函數首次被調用。
mounted()
初始化顯示之後。立即調用。是最常用的 callback,用來「掛載」到頁面上。
el
選項的 DOM 節點 被新創建的vm.$el
替換,並掛載到實例上去之後調用此生命週期方法。此時實例的資料在 DOM 節點上進行渲染。
2. 更新狀態顯示階段
this.xxx = value
beforeUpdate() 資料更新時調用
- 但不進行 DOM 重新渲染,在資料更新時 DOM 沒渲染前可以在這個生命方法裡進行狀態處理。
updated() 資料更新並且 DOM 重新渲染
- 這個狀態下資料更新並且 DOM 重新渲染,當這個生命週期方法被調用時,組件 DOM 已經更新,所以這時可以執行依賴於 DOM 的操作。當實例每次進行資料更新時 updated 都會執行。
當我們調用 vm.$destroy()時,就會進入下一個銷毀 Vue 實例的階段
3.死亡、銷毀 Vue 實例階段
也稱死亡,也就是沒有互動的功能。
beforeDestory() 實例銷毀之前調用
destoryed() 實例銷毀後調用
- Vue 實例銷毀後調用。調用後,Vue 實例指示的所有東西都會解綁定,所有的事件監聽器會被移除,所有的子實例也會被銷毀。
查看生命週期方法的順序範例
範例:一行字,每隔一秒會切換成隱藏。
在初始化之後,把初始化的值以v-show
的方式讓<p>
依定時器的規則顯示。
再設定一個按鈕,綁定可以銷毀 vm 的函式,當點擊按鈕時這個 vm 會銷毀而停止顯示或隱藏切換,這個定時器掛載到mounted()
之後,點擊按鈕雖然會停止文字顯示的切換,卻不會停止我們在定時器裡放的console.log('++++++')
,也表示「定時器」並沒有被銷毀。
要把整個定時器銷毀(進入銷毀 Vue 實例)階段,需要在beforeDestroy()
這個階段清除定時器,我們可使用clearInterval()
來清除定時器,但是如何找到我們要銷毀的定時器?可以在mounted()
階段的定時器,指向我們設定的變數this.intervalId = setInterval()
來讓清除定時器的函式找到。
在實例裡加入每個時期的生命週期方法,並用console.log
印出來,執行一下頁面就可看到其順序。
各生命週期執行次數
階段 | 生命週期 Hook | 執行次數 |
---|
| 初始化顯示階段
||beforeCreate() 實例創建前 | 1 次
| |created() 實例創建後 | 1 次 |
| | beforeMount() 在掛載開始之前 | 1 次
|| mounted() 掛載 | 1 次
| 更新狀態顯示階段
| | beforeUpdate() 資料更新時 | 不限次數 |
| | updated() 資料更新並 DOM 重新渲染 | 不限次數 |
| 死亡、銷毀 Vue 實例階段| | |
| | beforeDestory() 實例銷毀之前 | 1 次 |
| | destoryed() 實例銷毀後 | 1 次 |
常用的生命週期方法?
mounted()
:主要用來發送ajax
請求,啟動定時器等非同步的任務。beforeDestory()
:做收尾的工作,例如清除定時器,否則定時器會一直執行下去(如範例)created()
:進行 ajax 請求異步數據的獲取、初始化數據mounted()
:掛載元素內 dom 節點的獲取nextTick()
:針對單一事件更新數據後立即操作 domupdated()
:任何數據的更新,如果要做統一的業務邏輯處理watch()
:監聽具體數據變化,並做相應的處理
實際操作
來 codepen 看看:VueJs Instance Lifecycle Hooks 生命週期鉤子,別忘了觀察 console 的變化。
HTML 部分:
1 | <button @click="destroyVm">Destroy vm</button> |
Vue 實例的部分
1 | const vm = new Vue({ |