Vue父子元件生命週期

WindrunnerMax發表於2020-09-19

Vue父子元件生命週期

Vue例項需要經過建立、初始化資料、編譯模板、掛載DOM、渲染、更新、渲染、解除安裝等一系列過程,這個過程就是Vue的生命週期,Vue中提供的鉤子函式有beforeCreatecreatedbeforeMountmountedbeforeUpdateupdatedbeforeDestroydestroyed,父子元件巢狀時,父元件和子元件各擁有各自獨立的鉤子函式。

描述

建立過程

建立過程主要涉及beforeCreatecreatedbeforeMountmounted四個鉤子函式。

Parent beforeCreate -> Parent Created -> Parent BeforeMount -> Child BeforeCreate -> Child Created -> Child BeforeMount -> Child Mounted -> Parent Mounted

更新過程

更新過程主要涉及beforeUpdateupdated兩個鉤子函式,當父子元件有資料傳遞時才會有生命週期的比較。

Parent BeforeUpdate -> Child BeforeUpdate -> Child Updated -> Parent Updated

銷燬過程

銷燬過程主要涉及beforeDestroydestroyed兩個鉤子函式,本例直接呼叫vm.$destroy()銷燬整個例項以達到銷燬父子元件的目的。

Parent BeforeDestroy -> Child BeforeDestroy -> Child Destroyed -> Parent Destroyed

示例

<!DOCTYPE html>
<html>

<head>
    <title>Vue父子元件生命週期</title>
</head>

<body>
    <div id="app"></div>
</body>
<script src="https://cdn.bootcss.com/vue/2.4.2/vue.js"></script>
<script type="text/javascript">
    Vue.component("counter", {
        props: {
            count: { 
                type: Number,
                default: 0
            },
        },
        beforeCreate: function() {
            console.log("Child", "BeforeCreate");
        },
        created: function() {
            console.log("Child", "Created");
        },
        beforeMount: function() {
            console.log("Child", "BeforeMount");
        },
        mounted: function() {
            console.log("Child", "Mounted");
        },
        beforeUpdate: function() {
            console.log("Child", "BeforeUpdate");
        },
        updated: function() {
            console.log("Child", "Updated");
        },
        beforeDestroy: function() {
            console.log("Child", "BeforeDestroy");
        },
        destroyed: function() {
            console.log("Child", "Destroyed");
        },
        template: `
            <div>
                <div>{{count}}</div>
            </div>
        `
    })
    var vm = new Vue({
        el: '#app',
        data: function(){
            return {
                count: 1
            }
        },
        beforeCreate: function() {
            console.log("Parent", "BeforeCreate");
        },
        created: function() {
            console.log("Parent", "Created");
        },
        beforeMount: function() {
            console.log("Parent", "BeforeMount");
        },
        mounted: function() {
            console.log("Parent", "Mounted");
        },
        beforeUpdate: function() {
            console.log("Parent", "BeforeUpdate");
        },
        updated: function() {
            console.log("Parent", "Updated");
        },
        beforeDestroy: function() {
            console.log("Parent", "BeforeDestroy");
        },
        destroyed: function() {
            console.log("Parent", "Destroyed");
        },
        template: `
            <div>
                <counter :count="count"></counter> 
                <button @click="count++">++</button>
            </div>
        `
    })
</script>

</html>

生命週期

Vue生命週期鉤子函式功能示例,其中this.msg初始化賦值Vue Lifecycle,在更新過程中賦值為Vue Update

beforeCreate

Vue例項開始建立到beforeCreate鉤子執行的過程中主要進行了一些初始化操作,例如元件的事件與生命週期鉤子的初始化。在此生命週期鉤子執行時元件並未掛載,datamethods等也並未繫結,此時主要可以用來載入一些與Vue資料無關的操作,例如展示一個loading等。

console.log("beforeCreate");
console.log(this.$el); //undefined
console.log(this.$data); //undefined 
console.log(this.msg); // undefined
console.log("--------------------");

created

beforeCreatecreated的過程中主要完成了資料繫結的配置、計算屬性與方法的掛載、watch/event事件回撥等。在此生命週期鉤子執行時元件未掛載到到DOM,屬性$el目前仍然為undefined,但此時已經可以開始操作datamethods等,只是頁面還未渲染,在此階段通常用來發起一個XHR請求。

console.log("created");
console.log(this.$el); //undefined
console.log(this.$data); //{__ob__: Observer} 
console.log(this.msg); // Vue Lifecycle
console.log("--------------------");

beforeMount

createdbeforeMount的過程中主要完成了頁面模板的解析,在記憶體中將頁面的資料與指令等進行解析,當頁面解析完成,頁面模板就存在於記憶體中。在此生命週期鉤子執行時$el被建立,但是頁面只是在記憶體中,並未作為DOM渲染。

console.log("beforeMount");
console.log(this.$el); //<div id="app">...</div>
console.log(this.$data); // {__ob__: Observer}
console.log(this.msg); // Vue Lifecycle
console.log("--------------------");

mounted

beforeMountmounted的過程中執行的是將頁面從記憶體中渲染到DOM的操作。在此生命週期鉤子執行時頁面已經渲染完成,元件正式完成建立階段的最後一個鉤子,即將進入執行中階段。此外關於渲染的頁面模板的優先順序,是render函式 > template屬性 > 外部HTML

console.log("mounted");
console.log(this.$el); //<div id="app">...</div>
console.log(this.$data); //{__ob__: Observer} 
console.log(this.msg); // Vue Lifecycle
console.log("--------------------");

beforeUpdate

當資料發生更新時beforeUpdate鉤子便會被呼叫,此時Vue例項中資料已經是最新的,但是在頁面中的資料還是舊的,在此時可以進一步地更改狀態,這不會觸發附加的重渲染過程。在上述例子中加入了debugger斷點,可以觀察到Vue例項中資料已經是最新的,但是在頁面中的資料還是舊的。

// this.msg = "Vue Update";
console.log("beforeUpdate");
console.log(this.$el); //<div id="app">...</div>
console.log(this.$data); //{__ob__: Observer} 
console.log(this.msg); // Vue Update
console.log("--------------------");

updated

當資料發生更新並在DOM渲染完成後updated鉤子便會被呼叫,在此時元件的DOM已經更新,可以執行依賴於DOM的操作。

// this.msg = "Vue Update";
console.log("updated");
console.log(this.$el); //<div id="app">...</div>
console.log(this.$data); //{__ob__: Observer} 
console.log(this.msg); // Vue Update
console.log("--------------------");

beforeDestroy

Vue例項被銷燬之前beforeDestroy鉤子便會被呼叫,在此時例項仍然完全可用。

// this.$destroy();
console.log("beforeDestroy");
console.log(this.$el); //<div id="app">...</div>
console.log(this.$data); //{__ob__: Observer} 
console.log(this.msg); // Vue Update
console.log("--------------------");

destroyed

Vue例項被銷燬之後destroyed鉤子便會被呼叫,在此時Vue例項繫結的所有東西都會解除繫結,所有的事件監聽器會被移除,所有的子例項也會被銷燬,元件無法使用,datamethods也都不可使用,即使更改了例項的屬性,頁面的DOM也不會重新渲染。

// this.$destroy();
console.log("destroyed");
console.log(this.$el); //<div id="app">...</div>
console.log(this.$data); //{__ob__: Observer} 
console.log(this.msg); // Vue Update
console.log("--------------------");

每日一題

https://github.com/WindrunnerMax/EveryDay

參考

https://segmentfault.com/a/1190000011381906
https://www.cnblogs.com/yuliangbin/p/9348156.html
https://www.cnblogs.com/zmyxixihaha/p/10714217.html

相關文章