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>