Vue.js-07:第七章 - Vue 例項的生命週期
一、前言
在之前的 Vue 學習中,我們在使用 Vue 時,都會建立一個 Vue 的例項,而每個 Vue 例項在被建立時都要經過一系列的初始化過程。例如,需要設定資料監聽、編譯模板、將例項掛載到 DOM 並在資料變化時更新 DOM 等。在這個過程中,Vue 會執行一些生命週期鉤子函式,而我們則可以在鉤子函式中編寫一些自定義方法,用以在 Vue 的整個生命週期中某些階段實現我們特殊需求。那麼,本章,我們就來了解 Vue 例項的生命週期鉤子函式。
學習系列目錄地址:https://www.cnblogs.com/danvic712/p/9549100.html
倉儲地址:
二、乾貨合集
在我們使用 Vue 的時候,都會先建立一個 Vue 例項,這個例項不僅是我們掛載 Vue 框架的入口,也是 MVVM 思想中的 VM(ViewModel)。在我們使用 Vue 的整個過程中,歸根結底都是在對這個 Vue 例項進行操作。因此,只有當我們瞭解 Vue 例項的生命週期之後,才可以更好的實現我們的業務邏輯。
在 Vue 官網的這張生命週期圖示中,我們可以看到整個生命週期中包含了8個鉤子函式:beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed。從字面意思我們就可以清楚的看出來,這8個鉤子函式兩個一組,分別對應於 Vue 例項的建立、掛載、更新、銷燬,接下來,我們就根據這四個階段,解釋 Vue 例項各個階段中的鉤子函式的作用。
1、beforeCreate & created
在我們通過 new Vue() 建立了一個 Vue 例項之後,會執行 init 方法,此時只會初始化 Vue 例項所包含的一些預設的事件與生命週期函式,在這個例項還未被完全建立之前,則會執行我們的 beforeCreate 鉤子函式。
在下面的例子中,我們在例項化 Vue 物件時,自定義了一個 message 屬性,同時設定了一個 show 方法,現在我們來看看當例項並沒有完全被建立之前,是否能夠獲取到我們自定義的屬性與方法。
<div id="app"> {{message}} </div> <script> var vm = new Vue({ el: '#app', data: { message: 'Hello World!' }, methods: { show() { console.log('執行了 show 方法'); } }, beforeCreate() { console.log(`Vue 例項掛載物件 el:${this.$el}`) console.log(`Vue 例項的 data 物件:${this.$data}`) console.log(`Vue 例項的 message 屬性值:${this.message}`) console.log(`Vue 例項的 methods 物件:${this.$options.methods}`) this.show(); } }) </script>
從瀏覽器的控制檯中我們可以看到,此時,Vue 例項中的 data、methods 物件,或是我們定義的 Vue 例項的掛載點元素,在 beforeCreated 生命週期鉤子函式執行時,都沒有進行了初始化。
當 beforeCreated 鉤子函式執行完成後,Vue 例項已經初始化完成,此時將要執行生命週期中的 created 鉤子函式來監聽我們對於資料的更改或是監聽事件。
<div id="app"> {{message}} </div> <script> var vm = new Vue({ el: '#app', data: { message: 'Hello World!' }, methods: { show() { console.log('執行了 show 方法'); } }, created() { console.log(`Vue 例項掛載物件 el:${this.$el}`) console.log(`Vue 例項的 data 物件:${this.$data}`) console.log(`Vue 例項的 message 屬性值:${this.message}`) console.log(`Vue 例項的 methods 物件:${this.$options.methods}`) this.show(); } }) </script>
從瀏覽器控制檯打印出的資訊可以看出,在執行 created 鉤子函式的過程中,對於自定義的屬性 message、自定義的方法 show 已經初始化完成,此時,整個 Vue 例項已經初始化完成。但是,對於我們的 Vue 例項的掛載點元素還沒有進行初始化。也就是說,當執行完 created 之後,Vue 例項與 View(檢視層)之間依舊是處於隔離的狀態,初始化完成的 Vue 例項也依舊沒有與 DOM 進行繫結。
2、beforeMount & mounted
當 Vue 例項執行完 beforeCreated、created 鉤子函式之後,Vue 例項已經初始化完成,而 Vue 例項並沒有掛載到頁面的 DOM 上。在掛載到頁面 DOM 元素之前,則需要執行 beforeMount 鉤子函式將我們的例項繫結到模板上進行編譯渲染。
<div id="app"> <h3 id="h3">{{message}}</h3> </div> <script> var vm = new Vue({ el: '#app', data: { message: 'Hello World!' }, methods: { show() { console.log('執行了 show 方法'); } }, beforeMount() { console.log(document.getElementById('h3').innerText) } }) </script>
從控制檯輸出的資訊可以看到,當執行到 beforeMount 鉤子函式時,已經將模板編譯完成,但是尚未掛載到頁面上去。
當把編譯完成的模板掛載到頁面上時,則需要執行 mounted 鉤子函式,在這個階段,使用者就可以看到已經渲染好的頁面。
<div id="app"> <h3 id="h3">{{message}}</h3> </div> <script> var vm = new Vue({ el: '#app', data: { message: 'Hello World!' }, methods: { show() { console.log('執行了 show 方法'); } }, mounted() { console.log(document.getElementById('h3').innerText) } }) </script>
這裡我們可以看到,已經可以獲取到差值表示式的值,即當執行到 mounted 鉤子函式時,頁面已經渲染完成了。
從上面的例子中可以看出,mounted 是建立 Vue 例項過程中的最後一個生命週期鉤子函式,當執行完 mounted 鉤子函式之後,例項已經被完成建立好,並已經渲染到頁面中,此時,如果我們不對例項進行任何的操作的話,Vue 例項則不會執行 新的生命週期鉤子函式。
3、beforeUpdate & updated
在執行完了 mounted 鉤子函式之後,Vue 例項實際已經脫離了例項的建立階段,進入例項的執行階段。此時,當我們對例項的 data 進行修改時,則會觸發 beforeUpdate、updated 這兩個鉤子函式。
<div id="app"> <h3 id="h3">{{message}}</h3> </div> <script> var vm = new Vue({ el: '#app', data: { message: 'Hello World!' }, methods: { show() { console.log('執行了 show 方法'); } }, beforeUpdate() { console.log(`頁面上的資料:${document.getElementById('h3').innerText}`) console.log(`data 中的 message 資料:${this.message}`) } }) </script>
我們可以看到,當我們對 data 中的 message 屬性進行修改時,在執行 beforeUpdate 鉤子函式時,頁面上的資料還是舊的資料,而 data 中 message 屬性已經將值修改成了最新的值(這裡頁面上顯示的為修改後的資料則是因為執行了後面的鉤子函式,將修改後的資料同步渲染到了頁面上)。
Vue 作為一個具有資料雙向繫結特性的框架,當我們實時修改了頁面元素的值之後,肯定希望頁面可以同步變更資料。而在執行 beforeUpdate 鉤子函式之後,我們已經在例項中修改了資料,現在只需要重新渲染到頁面就可以了,這時候,則會執行 updated 鉤子函式。
<div id="app"> <h3 id="h3">{{message}}</h3> </div> <script> var vm = new Vue({ el: '#app', data: { message: 'Hello World!' }, methods: { show() { console.log('執行了 show 方法'); } }, updated() { console.log(`頁面上的資料:${document.getElementById('h3').innerText}`) console.log(`data 中的 message 資料:${this.message}`) } }) </script>
從控制檯可以看到,當 updated 鉤子函式執行的時候,頁面和 data 中的資料已經完成了同步,都顯示的是最新的資料。此時,整個頁面資料實時變更的操作也已經完成了。
4、beforeDestroy & destroyed
既然有 Vue 例項的建立,那麼在我們不需要 Vue 例項的時候就需要將這個例項進行銷燬。而 beforeDestroy 以及 destroyed 鉤子函式則會幫我們實現這一目的。
<div id="app"> {{message}} </div> <script> var vm = new Vue({ el: '#app', data: { message: 'Hello World!' }, methods: { show() { console.log('執行了 show 方法'); } }, beforeDestroy() { console.log(`Vue 例項掛載物件 el:${this.$el}`) console.log(`Vue 例項的 data 物件:${this.$data}`) console.log(`Vue 例項的 message 屬性值:${this.message}`) console.log(`Vue 例項的 methods 物件:${this.$options.methods}`) this.show(); }, destroyed() { console.log(`Vue 例項掛載物件 el:${this.$el}`) console.log(`Vue 例項的 data 物件:${this.$data}`) console.log(`Vue 例項的 message 屬性值:${this.message}`) console.log(`Vue 例項的 methods 物件:${this.$options.methods}`) this.show(); } }) </script>
這裡,我們手動銷燬 Vue 例項,從控制檯的輸出內容可以看到,在 beforeDestroy 和 destroyed 鉤子函式執行中,我們依舊可以獲取到 Vue 例項的相關內容,可是,當我們選擇更新 message 屬性的值時會發現,此時,頁面上顯示的值並沒有發生改變。原來,這裡的銷燬並不指代'抹去'這個 Vue 例項,而是表示將 Vue 例項與頁面的 DOM 元素進行'解綁'。
三、總結
鉤子函式 | 描述 |
---|---|
beforeCreate | Vue 例項進行初始化,此時例項的各個元件還沒有進行初始化完成,因此不能訪問到 data、computed、watch、methods 上的方法和資料,同時,Vue 例項的掛載點也沒有進行初始化 |
created | Vue 例項初始化完成,此時可以訪問 data、computed、watch、methods 上的方法和資料,但是依舊沒有進行 Vue 例項的掛載點初始化 |
beforeMount | 將例項繫結到模板並進行渲染,但並不會將例項掛載到頁面上 |
mounted | 將渲染好的模板繫結到頁面上,此時,Vue 例項已完全建立好 |
beforeUpdate | 資料變更時呼叫,在例項資料更改之前執行任何應該發生的自定義邏輯或操作 |
updated | 將 Vue 例項更新完成的資料重新渲染到記憶體中的虛擬 DOM 上,再將虛擬 DOM 應用到頁面上 |
beforeDestroy | Vue 例項進入銷燬階段,此時例項上的 data、methods、過濾器、指令等等還是處於可用的狀態,還沒有真正執行銷燬的過程(解除與頁面 DOM 元素的繫結) |
destroyed | 例項被銷燬(解除與頁面 DOM 元素的繫結) |