1. 程式人生 > >Vue.js之生命週期

Vue.js之生命週期

有時候,我們需要在例項建立過程中進行一些初始化的工作,以幫助我們完成專案中更復雜更豐富的需求開發,針對這樣的需求,Vue提供給我們一系列的鉤子函式。

vue生命週期

beforeCreate

在例項初始化之後,資料觀測 (data observer) 和 event/watcher 事件配置之前被呼叫。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <
script src="../statics/vue.js"></script> </head> <body> <div id="app"> {{ name }} <button @click="myClick">點選修改資料</button> </div> <script> new Vue({ el: "#app", // 在template中使用元件與在body中使用元件是一樣的
// template: `<cont></cont>`, data: { name: "Alex" }, methods: { init: function () { console.log(this.name); }, myClick: function () {
this.name = "Pizza"; } }, beforeCreate() { console.group("beforeCreate"); console.log("el: ", this.$el); console.log("data: ", this.$data); console.log("name: ", this.name); console.log("init: ", this.init); console.log("innerHTML: ", document.getElementById("app").innerHTML); }, }); </script> </body> </html>

效果:

created

在例項建立完成後被立即呼叫。在這一步,例項已完成以下的配置:資料觀測 (data observer),屬性和方法的運算,watch/event 事件回撥。然而,掛載階段還沒開始,$el 屬性目前不可見。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="static/vue.min.js"></script>
</head>
<body>

    <div id="app">
        {{ name }}
        <button @click="myClick">點選修改資料</button>
    </div>

    <script>

        new Vue({
            el: "#app",
            // 在template中使用元件與在body中使用元件是一樣的
            // template: `<cont></cont>`,
            data: {
                name: "Alex"
            },
            methods: {
                init: function () {
                    console.log(this.name);
                },
                myClick: function () {
                    this.name = "Pizza";
                }
            },
            beforeCreate() {
                console.group("beforeCreate");
                console.log("el: ", this.$el);
                console.log("data: ", this.$data);
                console.log("name: ", this.name);
                console.log("init: ", this.init);
                console.log("innerHTML: ", document.getElementById("app").innerHTML);
            },
            created() {
                console.group("Created");
                console.log("el: ", this.$el);
                console.log("data: ", this.$data);
                console.log("name: ", this.name);
                console.log("init: ", this.init);
                console.log("innerHTML: ", document.getElementById("app").innerHTML);
            }
        })
    </script>

</body>
</html>

beforeMount

在掛載開始之前被呼叫:相關的 render 函式首次被呼叫。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../statics/vue.js"></script>
</head>
<body>

    <div id="app">
        {{ name }}
        <button @click="myClick">點選修改資料</button>
    </div>

    <script>

        new Vue({
            el: "#app",
            // 在template中使用元件與在body中使用元件是一樣的
            // template: `<cont></cont>`,
            data: {
                name: "Alex"
            },
            methods: {
                init: function () {
                    console.log(this.name);
                },
                myClick: function () {
                    this.name = "Pizza";
                }
            },
            beforeCreate() {
                console.group("beforeCreate");
                console.log("el: ", this.$el);
                console.log("data: ", this.$data);
                console.log("name: ", this.name);
                console.log("init: ", this.init);
                console.log("innerHTML: ", document.getElementById("app").innerHTML);
            },
            created() {
                console.group("Created");
                console.log("el: ", this.$el);
                console.log("data: ", this.$data);
                console.log("name: ", this.name);
                console.log("init: ", this.init);
                console.log("innerHTML: ", document.getElementById("app").innerHTML);
            },
            beforeMount() {
                console.group("beforeMount");
                console.log("el: ", this.$el);
                console.log("data: ", this.$data);
                console.log("name: ", this.name);
                console.log("init: ", this.init);
                console.log("innerHTML: ", document.getElementById("app").innerHTML);
            }
        })
    </script>

</body>
</html>

mounted

el 被新建立的 vm.$el 替換,並掛載到例項上去之後呼叫該鉤子。如果 root 例項掛載了一個文件內元素,當 mounted 被呼叫時 vm.$el 也在文件內。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../statics/vue.js"></script>
</head>
<body>

    <div id="app">
        {{ name }}
        <button @click="myClick">點選修改資料</button>
    </div>

    <script>

        new Vue({
            el: "#app",
            // 在template中使用元件與在body中使用元件是一樣的
            // template: `<cont></cont>`,
            data: {
                name: "Alex"
            },
            methods: {
                init: function () {
                    console.log(this.name);
                },
                myClick: function () {
                    this.name = "Pizza";
                }
            },
            beforeCreate() {
                console.group("beforeCreate");
                console.log("el: ", this.$el);
                console.log("data: ", this.$data);
                console.log("name: ", this.name);
                console.log("init: ", this.init);
                console.log("innerHTML: ", document.getElementById("app").innerHTML);
            },
            created() {
                console.group("Created");
                console.log("el: ", this.$el);
                console.log("data: ", this.$data);
                console.log("name: ", this.name);
                console.log("init: ", this.init);
                console.log("innerHTML: ", document.getElementById("app").innerHTML);
            },
            beforeMount() {
                console.group("beforeMount");
                console.log("el: ", this.$el);
                console.log("data: ", this.$data);
                console.log("name: ", this.name);
                console.log("init: ", this.init);
                console.log("innerHTML: ", document.getElementById("app").innerHTML);
            },
            mounted() {
                console.group("mounted");
                console.log("el: ", this.$el);
                console.log("data: ", this.$data);
                console.log("name: ", this.name);
                console.log("init: ", this.init);
                console.log("innerHTML: ", document.getElementById("app").innerHTML);
            },
        })
    </script>

</body>
</html>

beforeUpdate

資料更新時呼叫,發生在虛擬 DOM 打補丁之前。這裡適合在更新之前訪問現有的 DOM,比如手動移除已新增的事件監聽器。

該鉤子在伺服器端渲染期間不被呼叫,因為只有初次渲染會在服務端進行.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../statics/vue.js"></script>
</head>
<body>

    <div id="app">
        {{ name }}
        <button @click="myClick">點選修改資料</button>
    </div>

    <script>

        new Vue({
            el: "#app",
            // 在template中使用元件與在body中使用元件是一樣的
            // template: `<cont></cont>`,
            data: {
                name: "Alex"
            },
            methods: {
                init: function () {
                    console.log(this.name);
                },
                myClick: function () {
                    this.name = "Pizza";
                }
            },
            beforeCreate() {
                console.group("beforeCreate");
                console.log("el: ", this.$el);
                console.log("data: ", this.$data);
                console.log("name: ", this.name);
                console.log("init: ", this.init);
                console.log("innerHTML: ", document.getElementById("app").innerHTML);
            },
            created() {
                console.group("Created");
                console.log("el: ", this.$el);
                console.log("data: ", this.$data);
                console.log("name: ", this.name);
                console.log("init: ", this.init);
                console.log("innerHTML: ", document.getElementById("app").innerHTML);
            },
            beforeMount() {
                console.group("beforeMount");
                console.log("el: ", this.$el);
                console.log("data: ", this.$data);
                console.log("name: ", this.name);
                console.log("init: ", this.init);
                console.log("innerHTML: ", document.getElementById("app").innerHTML);
            },
            mounted() {
                console.group("mounted");
                console.log("el: ", this.$el);
                console.log("data: ", this.$data);
                console.log("name: ", this.name);
                console.log("init: ", this.init);
                console.log("innerHTML: ", document.getElementById("app").innerHTML);
            },
            beforeUpdate() {
                console.group("beforeUpdate");
                console.log("el: ", this.$el);
                console.log("data: ", this.$data);
                console.log("name: ", this.name);
                console.log("init: ", this.init);
                console.log("innerHTML: ", document.getElementById("app").innerHTML);
            }
        })
    </script>

</body>
</html>

updated

由於資料更改導致的虛擬 DOM 重新渲染和打補丁,在這之後會呼叫該鉤子。

當這個鉤子被呼叫時,元件 DOM 已經更新,所以你現在可以執行依賴於 DOM 的操作。然而在大多數情況下,你應該避免在此期間更改狀態。如果要相應狀態改變,通常最好使用計算屬性或 watcher 取而代之。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../statics/vue.js"></script>
</head>
<body>

    <div id="app">
        {{ name }}
        <button @click="myClick">點選修改資料</button>
    </div>

    <script>

        new Vue({
            el: "#app",
            // 在template中使用元件與在body中使用元件是一樣的
            // template: `<cont></cont>`,
            data: {
                name: "Alex"
            },
            methods: {
                init: function () {
                    console.log(this.name);
                },
                myClick: function () {
                    this.name = "Pizza";
                }
            },
            beforeCreate() {
                console.group("beforeCreate");
                console.log("el: ", this.$el);
                console.log("data: ", this.$data);
                console.log("name: ", this.name);
                console.log("init: ", this.init);
                console.log("innerHTML: ", document.getElementById("app").innerHTML);
            },
            created() {
                console.group("Created");
                console.log("el: ", this.$el);
                console.log("data: ", this.$data);
                console.log("name: ", this.name);
                console.log("init: ", this.init);
                console.log("innerHTML: ", document.getElementById("app").innerHTML);
            },
            beforeMount() {
                console.group("beforeMount");
                console.log("el: ", this.$el);
                console.log("data: ", this.$data);
                console.log("name: ", this.name);
                console.log("init: ", this.init);
                console.log("innerHTML: ", document.getElementById("app").innerHTML);
            },
            mounted() {
                console.group("mounted");
                console.log("el: ", this.$el);
                console.log("data: ", this.$data);
                console.log("name: ", this.name);
                console.log("init: ", this.init);
                console.log("innerHTML: ", document.getElementById("app").innerHTML);
            },
            beforeUpdate() {
                console.group("beforeUpdate");
                console.log("el: ", this.$el);
                console.log("data: ", this.$data);
                console.log("name: ", this.name);
                console.log("init: ", this.init);
                console.log("innerHTML: ", document.getElementById("app").innerHTML);
            },
            updated() {
                console.log("updated");
                console.log("el: ", this.$el);
                console.log("data: ", this.$data);
                console.log("name: ", this.name);
                console.log("init: ", this.init);
                console.log("innerHTML: ", document.getElementById("app").innerHTML);
            }
        })
    </script>

</body>
</html>

activated

keep-alive 元件啟用時呼叫。<keep-alive> 包裹動態元件時,會快取不活動的元件例項,而不是銷燬它們

該鉤子在伺服器端渲染期間不被呼叫。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../statics/vue.min.js"></script>
</head>
<body>

    <div id="app">
        <App></App>
    </div>

    <script>
        let Laside = {
            template: `
                <div>
                    <h1>{{ message }}</h1>
                    <button @click="changeData">點選修改資料</button>
                </div>
            `,

            data () {
                return {
                    message: "Hello Vue!"
                }
            },

            methods: {
                init: function () {
                    console.log(this.message)
                }
                changeData: function () {
                    this.mes = "Pizza is here!";
                }
            },

            // 元件的建立和銷燬對效能有影響
            beforeDestroy () {
                console.log("beforeDestroy");
            },

            destroyed () {
                console.log("destroyed");
            },

            activated () {
                console.group("activated");
                console.log("el: ", this.$el);
                console.log("data: ", this.$data);
                console.log("message: ", this.message);
                console.log("init: ", this.init);
                console.log("innerHTML: ", document.getElementById("app").innerHTML);
            },
        };

        let App = {
            template: `
                <div >
                    <keep-alive>
                        <Laside v-if="isShow"></Laside>
                    </keep-alive>
                    <button @click="showHide">建立消除元件</button>
                </div>
            `,
            components: {
                "Laside": Laside,
            },
            methods: {
                showHide: function () {
                    this.isShow = !this.isShow;
                }
            },
            data () {
                return {
                    isShow: true,
                }
            }
        };

        new Vue({
            el: "#app",
            // 在template中使用元件與在body中使用元件是一樣的
            // template: `<cont></cont>`,
            components: {
                App,
            }
        })
    </script>

</body>
</html>

deactivated

keep-alive 元件停用時呼叫。

該鉤子在伺服器端渲染期間不被呼叫。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../statics/vue.min.js"></script>
</head>
<body>

    <div id="app">
        <App></App>
    </div>

    <script>
        let Laside = {
            template: `
                <div>
                    <h1>{{ mes }}</h1>
                    <button @click="changeData">點選修改資料</button>
                </div>
            `,

            data () {
                return {
                    message: "Hello Vue!"
                }
            },

            methods: {
                init: function () {
                    console.log(this.message);
                }
                changeData: function () {
                    this.mes = "Pizza is here!";
                }
            },

            // 元件的建立和銷燬對效能有影響
            beforeDestroy () {
                console.log("beforeDestroy");
            },

            destroyed () {
                console.log("destroyed");
            },

            activated () {
                console.group("activated");
                console.log("el: ", this.$el);
                console.log("data: ", this.$data);
                console.log("message: ", this.message);
                console.log("init: ", this.init);
                console.log("innerHTML: ", document.getElementById("app").innerHTML);
            },

            deactivated () {
                console.group("deactivated");
                console.log("el: ", this.$el);
                console.log("data: ", this.$data);
                console.log("name: ", this.name);
                console.log("init: ", this.init);
                console.log("innerHTML: ", document.getElementById("app").innerHTML);
            }
        };

        let App = {
            template: `
                <div >
                    <keep-alive>
                        <Laside v-if="isShow"></Laside>
                    </keep-alive>
                    <button @click="showHide">建立消除元件</button>
                </div>
            `,
            components: {
                "Laside": Laside,
            },
            methods: {
                showHide: function () {
                    this.isShow = !this.isShow;
                }
            },
            data () {
                return {
                    isShow: true,
                }
            }
        };

        new Vue({
            el: "#app",
            // 在template中使用元件與在body中使用元件是一樣的
            // template: `<cont></cont>`,
            components: {
                App,
            }
        })
    </script>

</body>
</html>

beforeDestroy

例項銷燬之前呼叫。在這一步,例項仍然完全可用。頻繁的建立和銷燬元件對效能的影響很大,因此可以使用activated和deactivated。

該鉤子在伺服器端渲染期間不被呼叫。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../statics/vue.js"></script>
</head>
<body>

    <div id="app">
        <App></App>
    </div>

    <script>
        let Laside = {
            template: `
                <div>
                    <h1>{{ mes }}</h1>
                    <button @click="changeData">點選修改資料</button>
                </div>
            `,

            data () {
                return {
                    mes: "Hello Vue!"
                }
            },

            methods: {
                changeData: function () {
                    this.mes = "Pizza is here!";
                }
            },

            // 元件的建立和銷燬對效能有影響
            beforeDestroy() {
                console.log("beforeDestroy");
                console.log("el: ", this.$el);
                console.log("data: ", this.$data);
                console.log("name: ", this.name);
                console.log("init: ", this.init);
                console.log("innerText: ", document.getElementById("app").innerText);
                console.log("innerHTML: ", document.getElementById("app").innerHTML);
            },
        };

        let App = {
            template: `
                <div >
                    <Laside v-if="isShow"></Laside>
                    <button @click="showHide">建立消除元件</button>
                </div>
            `,
            components: {
                "Laside": Laside,
            },
            methods: {
                showHide: function () {
                    this.isShow = !this.isShow;
                }
            },
            data () {
                return {
                    isShow: true,
                }
            }
        };

        new Vue({
            el: "#app",
            // 在template中使用元件與在body中使用元件是一樣的
            // template: `<cont></cont>`,
            components: {
                App,
            }
        })
    </script>

</body>
</html>

destroyed

Vue 例項銷燬後呼叫。呼叫後,Vue 例項指示的所有東西都會解繫結,所有的事件監聽器會被移除,所有的子例項也會被銷燬。

該鉤子在伺服器端渲染期間不被呼叫。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../statics/vue.min.js"></script>
</head>
<body>

    <div id="app">
        <App></App>
    </div>

    <script>
        let Laside = {
            template: `
                <div>
                    <h1>{{ mes }}</h1>
                    <button @click="changeData">點選修改資料</button>
                </div>
            `,

            data () {
                return {
                    mes: "Hello Vue!"
                }
            },

            methods: {
                changeData: function () {
                    this.mes = "Pizza is here!";
                }
            },

            // 元件的建立和銷燬對效能有影響
            beforeDestroy() {
                console.log("beforeDestroy");
                console.log("el: ", this.$el);
                console.log("data: ", this.$data);
                console.log("name: ", this.name);
                console.log("init: ", this.init);
                console.log("innerHTML: ", document.getElementById("app").innerHTML);
            },

            destroyed () {
                console.log("destroyed");
                console.log("el: ", this.$el);
                console.log("data: ", this.$data);
                console.log("name: ", this.name);
                console.log("init: ", this.init);
                console.log("innerHTML: ", document.getElementById("app").innerHTML);
            }
        };

        let App = {
            template: `
                <div >
                    <Laside v-if="isShow"></Laside>
                    <button @click="showHide">建立消除元件</button>
                </div>
            `,
            components: {
                "Laside": Laside,
            },
            methods: {
                showHide: function () {
                    this.isShow = !this.isShow;
                }
            },
            data () {
                return {
                    isShow: true,
                }
            }
        };

        new Vue({
            el: "#app",
            // 在template中使用元件與在body中使用元件是一樣的
            // template: `<cont></cont>`,
            components: {
                App,
            }
        })
    </script>

</body>
</html>