Vuejs
介紹完如何使用 new Vue({...})
建構 Vue instance 後,接著來談論有關 Vue instance 的生命週期。何謂生命週期?生命週期指的便是一個 Vue instance 自 創建
到 銷毀
的過程中需要歷經的系列步驟,包含設置 data observer
、編譯 template
、將 Vue instance 掛載到 DOM 上、data
更動 Virtual DOM 重新打補丁等。
而上述的過程 Vue 提供各個階段的 Lifecycle Hooks 使得開發者可以在 Vue instance Lifecycle 的各個階段執行特定的程式碼,相當於在每個階段可以寫入對應的 callback
執行其他動作,例如資料請求等。
進入介紹 Lifecycle Hooks 各個階段前,先來一個簡易的 Vue instance 掛載過程,並在各個 Lifecycle Hooks 使用 alert (lifecycle Hook Name) 方便觀察:
<main>
<h1>還沒掛載 vue instance 的原始頁面</h1>
</main>
const vm = new Vue({
el: 'main',
template: `
<main class="bg-green">
<h1>已經掛載 vue instance 的頁面</h1>
</main>
`,
beforeCreate () {
alert('beforeCreate')
},
created () {
alert('created')
},
beforeMount () {
alert('beforeMount')
},
mounted () {
alert('mounted')
},
beforeUpdate () {
alert('beforeUpdate')
},
updated () {
alert('updated')
},
beforeDestroy () {
alert('beforeDestroy')
},
destroyed () {
alert('destroyed')
},
})
在該範例中,我們創建了一個 root Vue instance 取代掛載的 el
main
,Vue instance 創建後,我們可以看到歷經以下步驟:
beforeCreate
Hookcreate
Hooktemplate
相關渲染函式 -> 對應 beforeMounted
Hookvm.$el
替換 el
元素。 -> 對應 mounted
Hook
紫色
轉換成 綠色
。在此簡單範例中,我們看到了 Vue instance 中 Lifecycle Hooks 何時被調用,下面詳細介紹各個階段 Lifecycle Hooks:
注:Vue2 版
在 Vue instance 初始後,data observer
設置前。
透過設定 console.log()
我們可以來觀察 Vue instance 目前的狀態。
在 Option 物件中添加以下程式碼:
補充:由於會有多個生命週期 Hooks 的
console
結果,推薦使用console.group
幫助檢視。
beforeCreate() {
alert('beforeCreate')
console.group('beforeCreate')
console.log('this', this)
console.log('this.$el', this.$el)
console.log('this.$data', this.$data)
console.groupEnd('beforeCreate')
},
由於此時 Vue instance 尚未完成 $data
、$el
綁定,所以此時兩者皆為 undefined
。
$data |
$el |
---|---|
undefined | undefined |
Vue instance 完成 data observe
,$data
可用,$el
尚未掛載,不可用。
在 Option 物件中添加以下程式碼:
created() {
alert('created')
console.group('created')
console.log('this', this)
console.log('this.$el', this.$el)
console.log('this.$data', this.$data)
console.groupEnd('created')
},
$data |
$el |
---|---|
可用 | undefined |
$el
掛載前被呼叫。
在 Option 物件中添加以下程式碼:
beforeMount() {
alert('beforeMount')
console.group('beforeMount')
console.log('this', this)
console.log('this.$el', this.$el)
console.log('this.$data', this.$data)
console.groupEnd('beforeMount')
},
$data |
$el |
---|---|
可用 | 有值 |
此部分的
$el
打印結果目前測試為尚未渲染的el
,正在研究中 ⚙︎,之後會補上理解
Vue instance 掛載取代 el
後呼叫,此時原先的 el
已經被 $el
取代。
在 Option 物件中添加以下程式碼:
mounted() {
alert('mounted')
console.group('mounted')
console.log('this', this)
console.log('this.$el', this.$el)
console.log('this.$data', this.$data)
console.groupEnd('mounted')
},
$data |
$el |
---|---|
可用 | 可用 |
資料更新時調用,發生在 Virtual DOM 打補丁前。
在 Option 物件中添加以下程式碼:
beforeUpdate() {
alert('beforeUpdate')
console.group('beforeUpdate')
console.log('this', this)
console.log('this.$el', this.$el)
console.log('this.$data', this.$data)
console.groupEnd('beforeUpdate')
},
接著要先更改 data,並且我們添加 {{ 要更改的資料 }}
到 template
中,滿足資料更新及會觸發 Virtual DOM 打補丁的條件,才會觸發該 Lifecycle Hook 調用。
添加以下程式碼:
...
template: `
<main class="bg-green">
<h1>已經掛載 vue instance 的頁面</h1>
<p>{{ word }}</p>
</main>
`,
data: {
word: 'init',
},
...
接著透過 Vue devtool 修改資料、或是在 console
輸入以下修改資料 vm.$data.word = 'change'
便可以看到該 Hook 調用。
更改 data
導致 Virtaul DOM 重新渲染後調用。
Vue instance 銷毀前調用。
使用 vm.$destory
觸發 Vue instance 銷毀。
vm.$destroy()
Vue instance 銷毀後調用,此時會移除 Vue instance 內的事件監聽器。
最後,我們來了解使用 Lifecycle Hook 要注意的細節。
Lifecycle Hooks 會自動綁定 this
context
為 Vue instance
,因此可以透過 this
訪問該 Vue instance。
由於上述原因,不可以使用 arrow function
定義 Hook,arrow function
沒有自己的 this
,其 this
值為所屬 lexical context
的 this
值,若是使用 arrow function
定義 Hook,Vue 將無法綁定 Vue instance 作為 Hook 的 this
值。
更多關於
this
,推薦可以閱讀這篇 淺談 JavaScript 頭號難題 this:絕對不完整,但保證好懂 。
以下使用 arrow function
this
值將不會是 vue instance 而為 window
,請不要如此:
const vm = new Vue({
el: 'main',
template: `
<main class="bg-green">
<h1>lifecycle hook and This</h1>
</main>
`,
// (X) 錯誤寫法
beforeCreate: () => {
console.log(this)
},
})
請使用以下寫法:
const vm = new Vue({
el: 'main',
template: `
<main class="bg-green">
<h1>lifecycle hook and This</h1>
</main>
`,
beforeCreate () {
console.log(this)
},
})
以上為此次內容,說明了有關 Instance Lifecycle,以及各個 instance Lifecycle Hook 調用的時機,感謝看到這裡的你,我們明天見。
若是文中有任何錯誤、錯字、想討論的內容,歡迎各位大大不吝鞭笞指正、交流分享,筆者不慎感激 ✦ ✦ ✦
▶︎ 筆者 github:https://github.com/YUN-RU-TSENG
▶︎ 老王賣瓜之筆者另一篇鐵人:每天來點 CSS Specification
▶︎ 倘若不斷向深處扎根,似乎就能茁壯成長 - RM
還有隱藏版的 lifecycle
active
deactive
nextTick
原本打算放在後面元件的部分介紹 actived
、deactived
,方法 $nextTick
就要來研究一下了 XD
我劇透了?!XD
感謝分享
補充 new Vue() 是 Vue 2 的語法,
Vue 3 用 Vue.createApp() 取代 new Vue()
https://book.vue.tw/appendix/migration.html#%E5%85%83%E4%BB%B6%E5%AF%A6%E9%AB%94%E5%BB%BA%E7%AB%8B
Vue 2 support will end on Dec 31, 2023. Learn more about Vue 2 Extended LTS.
The Benefits of the New Vue 3 App Initialization Code