[Vue 牛刀小試]:第七章 - 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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM