個人對vue中生命週期的理解

掘金小鋼炮發表於2019-05-11

前言

雖然現在網上有一大堆關於vue生命週期的文章,但我總覺得還是自己再來一遍理解更深,當然,我也看了很多關於vue生命週期的文章才寫出我自己的理解,不妥之處,不吝賜教!

官方圖解

首先,走流程,上官方圖解,注意,是官方圖解!

個人對vue中生命週期的理解

生命鉤子函式

什麼叫鉤子函式?我認為,鉤子就是隨時可能或者有需要時掛到什麼東西上,從而引發一些流血事件的發生。顯而易見,vue中的生命鉤子函式,就是隨時或者說在達到某一階段或條件時去觸發的函式,目的就是為了完成一些動作或者事件。需要注意的是,所有的生命週期鉤子自動繫結 this 上下文到例項中,因此你可以訪問資料,對屬性和方法進行運算。

通常我們所說的生命週期分為8個:分別為在初始化例項時,預設呼叫的beforeCreatecreatedbeforeMountmounted這四個鉤子函式,還有當更新資料時,更新之前會觸發beforeUpdate這個鉤子函式,更新完成之後,會觸發updated這個鉤子函式;當vue的例項銷燬時,會呼叫beforeDestroydestroyed這兩個鉤子函式。除此之外還有不常用的activateddeactivatederrorCaptured這三個鉤子函式,下面我會結合官方圖解逐一說一下。(我是不是很囉嗦啊)

過程

首先我們需要建立一個例項new Vue(),也就是在這個過程當中,首先執行了init(init是vue元件裡面預設去執行的),init Events & Lifecycle後先呼叫了beforeCreate,所以此時事件已經好了,也能開始使用生命週期函式了,然後繼續init injections(注射) & reactivity(反應性),在例項建立完成後它會立即呼叫created。在這一步,例項已完成以下的配置:資料觀測 (data observer),屬性和方法的運算,watch/event 事件回撥。所以在init的時候,事件已經呼叫了,我們在beforeCreate的時候千萬不要去修改data裡面賦值的資料,最早也要放在created裡面去做(新增一些行為)。

當created完成之後,它會去判斷instance(例項)裡面是否含有“el”option(選項),如果沒有的話,它會等待我們呼叫vm.$mount(el)這個方法,然後執行下一步;如果有的話,直接執行下一步。緊接著會判斷是否含有“template”這個選項,如果有,把 template 解析成一個 render function。render 函式會用 template 中的 html 去覆蓋 html 中的 div 標籤。在使用 .vue 檔案進行開發的過程中,是沒有 template 的,我們在 .vue 檔案中寫的 template 都經過了 vue-loader 處理,直接變成了 render 函式,放在vue-loader 解析過的檔案中;這樣做的好處,把 template 解析成 render 函式,比較耗時,vue-loader處理後,我們在頁面上執行程式碼時,效率會變高。如果沒有,Compile el's outerHTML as template。

beforeMount在有了render函式的時候才會執行,此時vue例項的$el和data都初始化了,但還是掛載之前為虛擬的dom節點。然後繼續執行render函式。當執行完render函式之後,也就是el被新建立的vm.$el替換,並掛載到例項上去之後就會呼叫mounted這個鉤子,在mounted掛載完畢之後,這個例項就算是走完流程了,此時el也被掛載到了真實DOM上。但是它不會承諾所有的子元件也都一起被掛載。如果你希望等到整個檢視都渲染完畢,可以用vm.$nextTick()。後續幾個鉤子函式,都是通過外部觸發進行的。

當資料更新變化時,beforeUpdate 執行,然後Virtual DOM re-render and patch最後updated 執行。

當元件銷燬時,beforeDestroy 執行,然後Teardown watchers,child comonents and event listeners,最後destroyed 執行。

然後說一下另外三個不常用的鉤子,首先activateddeactivated是和vue中一個原生的元件keep-alive有關係,當keep-alive元件啟用時呼叫activated鉤子。keep-alive 元件停用時呼叫deactivated鉤子。鉤子errorCaptured是當捕獲一個來自子孫元件的錯誤時被呼叫。此鉤子會收到三個引數:錯誤物件、發生錯誤的元件例項以及一個包含錯誤來源資訊的字串。此鉤子可以返回 false 以阻止該錯誤繼續向上傳播。

現在大家可以用程式碼測試一下鉤子函式的觸發順序,還有data資料和el渲染完畢的時間。

<div id="app">
    <input type="text" v-model="msg">//測試資料更新時的鉤子
    {{msg}}
</div>

let vm = new Vue({
        el:"#app",
        data: {
            msg:"data資料",
        },
        methods:{
            fn(){
              this.msg="改變data資料"
            }
        },
        beforeCreate(){
            // 建立之前;無法獲取響應資料
            console.log("beforeCreate","data:"+this.msg,"el:"+this.$el);
        },
        created(){
            // 建立之後
            console.log("created","data:"+this.msg,"el:"+this.$el);
        },
        beforeMount(){
            // 掛載前
            console.log("beforeMount","data:"+this.msg,"el:"+this.$el);
        },
        mounted(){
            // 掛載後
            console.log("mounted","data:"+this.msg,"el:"+this.$el);
        },
        beforeUpdate(){
            // 資料更新之前
            console.log("beforeUpdate","data:"+this.msg,"el:"+this.$el);
        },
        updated(){
            // 資料更新完成之後;
            console.log("updated","data:"+this.msg,"el:"+this.$el);
        },
        beforeDestroy(){
            // 銷燬之前
            console.log("beforeDestroy","data:"+this.msg,"el:"+this.$el);
        },
        destroyed(){
            // 銷燬之後
            console.log("destroyed","data:"+this.msg,"el:"+this.$el);
        }
    });
    // vm.$destroy();//測試銷燬元件呼叫的鉤子
    
    //測試結果
    //初始化過程
    beforeCreate data:undefined el:undefined
    created data:data資料 el:undefined
    beforeMount data:data資料 el:[object HTMLDivElement]
    mounted data:data資料 el:[object HTMLDivElement]
    
    //資料更新後
    beforeUpdate data:data資料更新 el:[object HTMLDivElement]
    updated data:data資料更新 el:[object HTMLDivElement]
    
    //資料銷燬後
    beforeDestroy data:data資料 el:[object HTMLDivElement]
    destroyed data:data資料 el:[object HTMLDivElement]

複製程式碼

其他一些總結

  • beforecreate : 可以在這加個loading事件
  • created :在這結束loading,還做一些初始資料的獲取,實現函式自執行
  • mounted : 在這發起後端請求,拿回資料,配合路由鉤子做一些事情
  • beforeDestroy: 你確認刪除XX嗎?
  • destroyed :當前元件已被刪除,清空相關內容

如果有不當之處,請指出來哈!!!還有啊,內容可能有點囉嗦,有點亂,勿噴!!!謝謝

相關文章