在Vue官網上一篇講到了Vue實例以及它的生命週期,這裏我將實例生命週期的圖截了下來如下:
我們可以看到在Vue實例的整個生命週期中,會有八個生命週期鉤子函數提供給我們,方便我們在不同時期進行不同操作,八個鉤子函數如下:
- beforeCreate
- created
- beforeMount
- mounted
- beforeUpdate
- updated
- beforeDestroy
- destroyed
先一起來看看下面代碼的打印結果:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">{{title}}</div>
<script type="text/javascript">
var vm = new Vue({
el:'#app',
data:{
title:"第一個例子"
},
beforeCreate(){
console.log("beforeCreate $el",this.$el) /*beforeCreate $el undefined*/
console.log("beforeCreate $data",this.$data) /*beforeCreate $data undefined*/
console.log("beforeCreate title",this.title) /*beforeCreate title undefined*/
},
created(){
console.log("created $el",this.$el) /* created $el undefined */
console.log("created $data",this.$data) /* created $data {__ob__: Observer} */
console.log("created title",this.title) /* created title 第一個例子 */
},
beforeMount(){
console.log("beforeMount $el",this.$el) /* beforeMount $el <div id="app">{{title}}</div> */
console.log("beforeMount $data",this.$data)/* beforeMount $data {__ob__: Observer} */
console.log("beforeMount title",this.title) /* beforeMount title 第一個例子 */
},
mounted(){
console.log("mounted $el",this.$el) /* mounted $el <div id="app">第一個例子</div> */
console.log("mounted $data",this.$data) /* mounted $data {__ob__: Observer} */
console.log("mounted title",this.title) /* mounted title 第一個例子 */
},
beforeUpdate() {
console.log("beforeUpdate $el",this.$el.innerHTML)
console.log("beforeUpdate $data",this.$data)
console.log("beforeUpdate title",this.title)
},
updated() {
console.log("updated $el",this.$el.innerHtml)
console.log("updated $data",this.$data)
console.log("updated title",this.title)
},
beforeDestroy(){
console.log("beforeDestroy $el",this.$el)
console.log("beforeDestroy $data",this.$data)
console.log("beforeDestroy title",this.title)
},
destroyed() {
console.log("destroyed $el",this.$el)
console.log("destroyed $data",this.$data)
console.log("destroyed title",this.title)
}
})
</script>
</body>
</html>
打印結果如下:
1. 在beforeCreate之前
進行了以下操作:(對於瀏覽器來說整個渲染還沒開始或者說準備開始, el 和 data 並未初始化 ,代碼中均打印的是undefined)
處理該實例的初始化選項:vm.$options
初始化生命週期:initLifecycle
初始化事件:initEvents
初始化render函數:initRender
beforeCreate()在這個函數中無法訪問el、data、method,因爲還未初始化。
2. beforeCreate和created之間
在這個期間對事件初始化、對數據進行觀測。通過代碼的打印結果我們可以看到,這期間data完成初始化,而el還不存在。所以我們對data進行賦值等其他操作時、或者調用method中的方法,最早只能在created()鉤子函數中!
3. created和beforeMount之間
根據流程圖,我們可以看到,先判斷vm實例中是否有el選項?
如果有:再判斷是否有template選項;
如果沒有:停止編譯(停止生命週期),直到調用vm.$mount(el)函數;
我們可以再之前的代碼上註釋掉:
el:'#app',
這一行,看到控制檯打印結果如下:生命週期在created之後就停止了,不往下執行!
我們在代碼中加上一行:
vm.$mount("#app")
打印結果如下:生命週期正常執行
以上是判斷是否存在el部分;如果存在el繼續判斷Vue實例中是否存在template選項:
如果有:將template作爲模板編譯成render函數;
如果沒有:將外部HTML作爲模板編譯;(上面的代碼例子中就未給出template屬性)
模板已經在內存中編譯好,但是未掛載到頁面中!
通過代碼打印我們可以看到,這個期間我們的el不再不存在,而是關聯到了我們指定的DOM上(打印出:<div id="app">{{title}}</div>)。
4. beforeMount和mounted之間
在這個期間,Vue實例在內存中創建了一個vm.$el,然後原本的el 被新創建的 vm.$el 替換,其實就是將內存中編譯好的模板替換到頁面上,之後調用mounted鉤子函數,所以我們在mounted函數中打印出來的el是:<div id="app">第一個例子</div> 頁面上的內容也隨之發生了變化!
顯然,如果我們要對頁面上的DOM進行操作時,最早只能在mounted()鉤子函數中進行。
當mounted()運行完後,整個實例的初始化階段結束,下面進入運行階段。
5. beforeUpdate鉤子函數和updated鉤子函數間的生命週期
當我們Vue實例中的data數據發生變化時就會觸發這兩個鉤子函數,如下:我們在控制檯輸入vm.title="121"來更改data數據,可以看到,在beforeUpdate時data中的數據已經修改爲了”121“(如果數據不改變,根本就不會觸發這兩個鉤子函數!!),但是我們的DOM中並未更新,而在updated時DOM已經更新了,頁面中已經顯示爲了”121“。
6. beforeDestroy和destroyed鉤子函數間的生命週期
beforeDestroy鉤子函數在實例銷燬之前調用,這時,實例仍然完全可用。
destroyed鉤子函數在Vue 實例銷燬後調用。調用後,Vue 實例指示的所有東西都會解綁定,所有的事件監聽器會被移除,所有的子實例也會被銷燬。我們使用vm.$destroy來銷燬實例如下:
但是頁面中的相應DOM並沒有變化,想要清除頁面的 DOM,需要使用 v-if="false"來手動銷燬實例 !
詳情可以參考官方文檔:官方文檔