Vue生命周期詳解


生命周期簡介

每個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生命周期內容,如果有哪里寫錯了,歡迎各位大佬指正,謝謝大家!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM