個人對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 :當前組件已被刪除,清空相關內容

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


免責聲明!

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



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