Vue生命週期詳解!!

在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>

打印結果如下:

image-1585912314822.png

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"來手動銷燬實例 ! 

詳情可以參考官方文檔:官方文檔

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章