vue生命週期詳解

小吳3發表於2021-09-07

生命週期簡介

每個Vue例項在被建立時都要經過一系列的初始化過程,例如:需要設定資料的監聽,編譯模板,將例項掛載到DOM上,並且在資料變化時更新DOM等,這些過程統稱為Vue例項的生命週期。同時在這個過程中也會執行一些叫做生命週期鉤子的函式,這給了使用者在不同階段新增自己的程式碼的機會。

其實Vue例項的生命週期,主要分為三個階段,每個階段都會執行不同的鉤子函式,分別為

  • 掛載(初始化相關屬性,例如watch屬性,method屬性)

    1. beforeCreate

    2. created

    3. beforeMount

    4. mounted

  • 更新(元素或元件的變更操作)

    1. beforeUpdate

    2. updated

  • 銷燬(銷燬相關屬性)

  1. beforeDestroy

  2. destroyed

 

下面請看一張Vue生命程式圖(圖片可能有點大)

鉤子函式:

第一步:

beforeCreate: Vue例項初始化之後,以及事件初始化,以及元件的父子關係確定後執行該鉤子函式,一般在開發中很少使用

created: 在呼叫該方法之前,初始化會被使用到的狀態,狀態包括props,methods,data,computed,watch.

而且會實現對data中屬性的監聽,也就是在created的時候資料已經和data屬性進行了繫結。(放在data中的屬性當值發生改變的時候,檢視也會改變)。同時也會對傳遞到元件中的資料進行校驗。

所以在執行created的時候,所有的狀態都初始化完成,我們也完全可以在該階段傳送非同步的ajax請求,獲取資料。

但是,在created方法中,是無法獲取到對應的的$el選項,也就是無法獲取Dom

請看如下程式碼:

 created() {
          console.log("created");
          console.log("el===", this.$el);// undefined
          console.log("data==", this.$data);// 可以獲取資料
          console.log("foo==", this.foo);//可以獲取資料
        },

第二步:

 

 

created方法執行完畢後,下面會判斷物件中有沒有el選項。如果有,繼續執行下面的流程,也就是判斷是否有template選項,

如果沒有el選項,則停止整個生命週期的流程,直到執行了vm.$mount(el)

下面請看程式碼:

<script>
      const vm = new Vue({
        // el: "#app",  //去掉了el選項
        data: {
          foo: "fooData",
        },
        methods: {
        beforeCreate() {
          console.log("beforCreate");
        },
        created() {
          console.log("created");
          console.log("el===", this.$el);
          console.log("data==", this.$data);
          console.log("foo==", this.foo);
        },      
      });
    </script>

在上面的程式碼中,我們將el選項去掉了,執行上面的程式碼後,我們發現執行完created方法後,整個流程就停止了。

現在,我們不新增el選項,但是手動執行vm.$mount(el),也能夠使暫停的生命週期進行下去。如下面程式碼

<script>
      const vm = new Vue({
        // el: "#app",//去掉了el選項
        data: {
          foo: "fooData",
        },
        methods: {      
        beforeCreate() {
          console.log("beforCreate");
        },
        created() {
          console.log("created");
          console.log("el===", this.$el);
          console.log("data==", this.$data);
          console.log("foo==", this.foo);
        },     
      });
      vm.$mount("#app");//新增了$mount方法
    </script>

下面請看圖

我們繼續向下看,就是判斷在物件中是否有template選項。

第一:如果Vue例項物件中有template引數選項,則將其作為模板編譯成render函式,來完成渲染。

第二:如果沒有template引數選項,則將外部的HTML作為模板編譯(template),也就是說,template引數選項的優先順序要比外部的HTML

第三:如果第一條,第二條件都不具備,則報錯

 

Vue需要通過el的“選擇器”找到對應的template.也就是說,Vue首先通過el引數去查詢對應的template.如果沒有找到template引數,則到外部HTML中查詢,找到後將模板編譯成render

函式(Vue的編譯實際上就是指Vue把模板編譯成render函式的過程)。還有一點需要注意template引數的優先順序比外部HTML的優先順序要高。)如果同時有template模板與外部的html,

則會優先渲染template裡面的資料

第三步:

接下來會觸發`beforeMount`這個鉤子函式:如下圖

在執行該鉤子函式的時候,虛擬`DOM`已經建立完成,馬上就要渲染了,在這裡可以更改`data`中的資料,不會觸發`updated`, 其實在`created`中也是可以更改資料,也不會觸發`updated`函式

測試程式碼如下:

beforeMount() {
          console.log("beforeMount");
          console.log("beforeMount el===", this.$el);
          console.log("data==", this.$data);
          //this.foo = "abc"; //修改資料
          console.log("foo==", this.foo);
        },

通過上面的程式碼,我們可以獲取`el`中的內容,同時也可以修改資料。

但是,這裡需要注意的輸入的`el`中的內容,`{{foo}}`還沒有被真正的資料替換掉。而且對應的內容還沒有掛載到頁面上。

下面執行了`Create VM.$el and replace "el" with it`

經過這一步後,在模板中所寫的`{{foo}}`會被具體的資料所替換掉。

所以下面執行`mounted`的時候,可以看到真實的資料。同時整個元件內容已經掛載到頁面中了,資料以及真實`DOM`都已經處理好了,可以在這裡操作真實`DOM`了,也就是在`mounted`的時候,頁面已經被渲染完畢了,在這個鉤子函式中,我們可以去傳送`ajax`請求。

第四步:如下圖

當整個元件掛在完成後,有可能會進行資料的修改,當Vue發現data中的資料發生了變化,會觸發對應元件的重新渲染,先後呼叫了beforeUpdate 和updated鉤子函式。

 

updated之前beoreUpdate之後有一個非常重要的操作就是虛擬DOM會重新構建,也就是新構建的虛擬DOM與上一次的虛擬DOM樹利用diff演算法進行對比之後重新渲染。

而到了updated這個方法,就表示資料已經更新完成,dom也重新render完成。

第五步:

下面如果我們呼叫了vm.$destroy方法後,就會銷燬所有的資源。

 

首先會執行beforeDestroy 這個鉤子函式,這個鉤子函式在例項銷燬前呼叫,在這一步,例項仍然可用。

在該方法中,可以做一些清理的工作,例如:清除定時器等。

但是執行到destroyed鉤子函式的時候,Vue例項已經被銷燬,所有的事件監聽器會被移除,所有的子例項也會被銷燬

最後來個總結:

beforeCreate( )// 該鉤子函式執行時,元件例項還未建立.
created()//元件初始化完畢,各種資料可以使用,可以使用ajax傳送非同步請求獲取資料
beforeMounted()// 未執行渲染,更新,虛擬DOM完成,真實DOM未建立
mounted()// 初始化階段結束,真實DOM已經建立,可以傳送非同步請求獲取資料,也可以訪問dom元素
beforeUpdate()//更新前,可用於獲取更新前各種狀態資料
updated()//更新後執行該鉤子函式,所有的狀態資料是最新的。
beforeDestroy() // 銷燬前執行,可以用於一些定時器的清除。
destroyed()//元件已經銷燬,事件監聽器被移除,所有的子例項也會被銷燬。

以上為vue生命週期內容,如果有哪裡寫錯了,歡迎各位大佬指正,謝謝大家!

相關文章