1. 程式人生 > >Vue.js-07:第七章 - Vue 例項的生命週期

Vue.js-07:第七章 - Vue 例項的生命週期

 一、前言

   在之前的 Vue 學習中,我們在使用 Vue 時,都會建立一個 Vue 的例項,而每個 Vue 例項在被建立時都要經過一系列的初始化過程。例如,需要設定資料監聽、編譯模板、將例項掛載到 DOM 並在資料變化時更新 DOM 等。在這個過程中,Vue 會執行一些生命週期鉤子函式,而我們則可以在鉤子函式中編寫一些自定義方法,用以在 Vue 的整個生命週期中某些階段實現我們特殊需求。那麼,本章,我們就來了解 Vue 例項的生命週期鉤子函式。

  學習系列目錄地址:https://www.cnblogs.com/danvic712/p/9549100.html

  倉儲地址:

https://github.com/Lanesra712/VueTrial/blob/master/Chapter01-Rookie/hocks.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 元素的繫結)

 四、參考

  1、詳解vue生命週期

  2、Vue2.0 探索之路——生命週期和鉤子函式的一些理解

  3、vue生命週期詳解

  4、vue生命週期探究(一)

  5、Vue生命週期深入

  6、Vue 資料繫結和響應式原理

  7、Vue.js – lifecycle hooks, the layman’s overview