Vue實戰之生命週期初探

Vue 生命週期之旅

每個 Vue 實例在被創建時都要經過一系列的初始化過程——例如,需要設置數據監聽、編譯模板、將實例掛載到 DOM 並在數據變化時更新 DOM 等。同時在這個過程中也會運行一些叫做生命週期鉤子的函數,這給了用戶在不同階段添加自己的代碼的機會

官方生命週期函數示意圖

vue生命週期示意圖

生命週期示意圖詳解
  • beforeCreate

在實例初始化之後,數據觀測 (data observer) 和 event/watcher 事件配置之前被調用
注意是數據觀測和事件/監聽配置之前調用,也就是說在此處訪問this.$el,this.$data,實例中的屬性或方法是訪問不到的,即undefined
使用場景:可以定義一些靜態屬性或者加載動畫

  • created

在實例創建完成後被立即調用。在這一步,實例已完成以下的配置:數據觀測 (data observer),屬性和方法的運算,watch/event 事件回調。然而,掛載階段還沒開始,$el 屬性目前不可見
datamethods 中的屬性和方法均可訪問,但vue實例的$em屬性仍然是undefined
使用場景:進行ajax請求異步數據的獲取、初始化數據,結束加載動畫

  • beforeMount

在掛載開始之前被調用:相關的 render 函數首次被調用。該鉤子在服務器端渲染期間不被調用。
由示意圖可知在created和beforeMount兩個鉤子期間,首先判斷是否有el屬性,如果沒有則生命週期終止,除非手動調用vm.$mount(el)方法,
如果有el屬性,則再判斷是否存在template,如果存在則編譯template並執行render函數,如果沒有則編譯外部html作爲模板進行編譯
注意:此時的$el不再是undefined,緊緊是字符串模板,相關數據還未填充,template的編譯優先級是高於outer html的
使用場景:

  • mounted

el 被新創建的 vm.$el 替換,並掛載到實例上去之後調用該鉤子。如果 root 實例掛載了一個文檔內元素,當 mounted 被調用時 vm.$el 也在文檔內。
注意 mounted 不會承諾所有的子組件也都一起被掛載。如果你希望等到整個視圖都渲染完畢,可以用 vm.$nextTick 替換掉 mounted,此時的$el爲填充後的數據
使用場景:當需要操作dom的時候執行,可以配合$.nextTick 使用進行單一事件對數據的更新後更新dom

  • beforeUpdate

數據更新時調用,發生在虛擬 DOM 打補丁之前。這裏適合在更新之前訪問現有的 DOM,比如手動移除已添加的事件監聽器。
該鉤子在服務器端渲染期間不被調用,因爲只有初次渲染會在服務端進行。
使用場景:在更新之前訪問現有的 DOM,比如手動移除已添加的事件監聽器。

  • updated

由於數據更改導致的虛擬 DOM 重新渲染和打補丁,在這之後會調用該鉤子。
當這個鉤子被調用時,組件 DOM 已經更新,所以你現在可以執行依賴於 DOM 的操作。然而在大多數情況下,你應該避免在此期間更改狀態。如果要相應狀態改變,通常最好使用計算屬性或 watcher 取而代之。
注意 updated 不會承諾所有的子組件也都一起被重繪。如果你希望等到整個視圖都重繪完畢,可以用 vm.$nextTick 替換掉 updated

  • beforeDestroy

實例銷燬之前調用。在這一步,實例仍然完全可用。該鉤子在服務器端渲染期間不被調用。
注意:我們可以使用 vm.$destroy()進行手動銷燬

  • destroyed

Vue 實例銷燬後調用。調用後,Vue 實例指示的所有東西都會解綁定,所有的事件監聽器會被移除,所有的子實例也會被銷燬。
該鉤子在服務器端渲染期間不被調用
注意:對data的改變不會再觸發周期函數,vue實例已解除事件監聽和dom綁定,但dom結構依然存在

生命週期以及使用場景
生命週期 解釋 使用場景
beforeCreate 在實例初始化之後,數據觀測 (data observer) 和 event/watcher 事件配置之前被調用 定義一些靜態屬性或者加載動畫,el data computed watch methods上的方法和數據均不能訪問
created 在實例創建完成後被立即調用。在這一步,實例已完成以下的配置:數據觀測 (data observer),屬性和方法的運算,watch/event 事件回調。然而,掛載階段還沒開始,$el 屬性目前不可見 初始化數據(計算或者轉換等),結束加載動畫
beforeMount 在掛載開始之前被調用:相關的 render 函數首次被調用 此時的$el是虛擬節點
mounted el 被新創建的 vm.$el 替換,並掛載到實例上去之後調用該鉤子 可異步請求,操作DOM
beforeUpdate 數據更新時調用,發生在虛擬 DOM 打補丁之前 這裏適合在更新之前訪問現有的DOM,比如手動移除已添加的事件監聽器
updated 由於數據更改導致的虛擬 DOM 重新渲染和打補丁,在這之後會調用該鉤子 可執行依賴的DOM操作
beforeDestroy 實例銷燬之前調用。在這一步,實例仍然完全可用 可用於銷燬定時器,解綁全局事件,銷燬插件對象
destroyed Vue 實例銷燬後調用。調用後,Vue 實例指示的所有東西都會解綁定,所有的事件監聽器會被移除,所有的子實例也會被銷燬 DOM依然存在
測試DEMO
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>vue</title>
        <script src="https://cdn.bootcss.com/vue/2.4.2/vue.js"></script>
    </head>
    <body>
        <div id="app">
            <div :style="{color:color}">
                <h6>{{ message + '這是在 outer html 中的' }}</h6>
            </div>
        </div>
    </body>
    <script>
        const vm = new Vue({
          el:'#app',
          //template:"<h1>{{message +'這是在 vue 實例template中的'}}</h1>",
          data:{
            message:'hello world',
            jumpUrl:'www.baidu.com',
            color:'orange'
          },
          methods:{
            tipTool(){
              return 'hello vue lifecycle';
            },
          },
          watch:{
            color:(new_value , old_value) => {
                alert('字體顏色監聽事件');
            }
          },
          beforeCreate:function(){
            //在實例初始化之後,數據觀測 (data observer) 和 event/watcher 事件配置之前被調用。
            this.refererUrl = 'www.sina.com';
            console.group('vue 生命週期 beforeCreate');
            console.log('vue實例的el',this.$el);
            console.log('vue實例的data',this.$data);
            console.log('vue實例的data中的數據 message ',this.message);
            console.log('vue實例的data中的數據 refererUrl ',this.refererUrl);
            const res = this.tipTool();
            console.log('vue實例的方法 ',res);
          },
          created:function(){
            // 在實例創建完成後被立即調用。在這一步,
            // 實例已完成以下的配置:數據觀測 (data observer),屬性和方法的運算,watch/event 事件回調。
            // 然而,掛載階段還沒開始,$el 屬性目前不可見。
            console.group('vue 生命週期 created');
            console.log('vue實例的el',this.$el);
            console.log('vue實例的data',this.$data);
            console.log('vue實例的data中的數據 message ',this.message);
            console.log('vue實例的data中的數據 refererUrl ',this.refererUrl);
            const res = this.tipTool();
            console.log('vue實例的方法 ',res);
          },
          beforeMount(){
            // 在掛載開始之前被調用:相關的 render 函數首次被調用。
            console.group('vue 生命週期 beforeMount');
            console.log('vue實例的el',this.$el);
            console.log('vue實例的data',this.$data);
            console.log('vue實例的data中的數據 message ',this.message);
            console.log('vue實例的data中的數據 refererUrl ',this.refererUrl);
            const res = this.tipTool();
            console.log('vue實例的方法 ',res);
          },
          mounted(){
            // el 被新創建的 vm.$el 替換,並掛載到實例上去之後調用該鉤子。
            // 如果 root 實例掛載了一個文檔內元素,當 mounted 被調用時 vm.$el 也在文檔內。
            // 注意 mounted 不會承諾所有的子組件也都一起被掛載。如果你希望等到整個視圖都渲染完畢,可以用 vm.$nextTick 替換掉 mounted
            console.group('vue 生命週期 mounted');
            console.log('vue實例的el',this.$el);
            console.log('vue實例的data',this.$data);
            console.log('vue實例的data中的數據 message ',this.message);
            console.log('vue實例的data中的數據 refererUrl ',this.refererUrl);
            const res = this.tipTool();
            console.log('vue實例的方法 ',res);
          },
          beforeUpdate(){
            // 數據更新時調用,發生在虛擬 DOM 打補丁之前。這裏適合在更新之前訪問現有的 DOM,比如手動移除已添加的事件監聽器。
            // 該鉤子在服務器端渲染期間不被調用,因爲只有初次渲染會在服務端進行
            console.group('vue 生命週期 beforeUpdate');
            console.log('vue實例的el',this.$el);
            console.log('vue實例的data',this.$data);
            console.log('vue實例的data中的數據 message ',this.message);
            console.log('vue實例的data中的數據 refererUrl ',this.refererUrl);
            const res = this.tipTool();
            console.log('vue實例的方法 ',res);
          },
          updated(){
            // 由於數據更改導致的虛擬 DOM 重新渲染和打補丁,在這之後會調用該鉤子。
            // 當這個鉤子被調用時,組件 DOM 已經更新,所以你現在可以執行依賴於 DOM 的操作。然而在大多數情況下,你應該避免在此期間更改狀態。如果要相應狀態改變,通常最好使用計算屬性或 watcher 取而代之。
            // 注意 updated 不會承諾所有的子組件也都一起被重繪。如果你希望等到整個視圖都重繪完畢,可以用 vm.$nextTick 替換掉 updated
            console.group('vue 生命週期 updated');
            console.log('vue實例的el',this.$el);
            console.log('vue實例的data',this.$data);
            console.log('vue實例的data中的數據 message ',this.message);
            console.log('vue實例的data中的數據 refererUrl ',this.refererUrl);
            const res = this.tipTool();
            console.log('vue實例的方法 ',res);
          },
          beforeDestroy(){
            //實例銷燬之前調用。在這一步,實例仍然完全可用
            console.group('vue 生命週期 beforeDestroy');
            console.log('vue實例的el',this.$el);
            console.log('vue實例的data',this.$data);
            console.log('vue實例的data中的數據 message ',this.message);
            console.log('vue實例的data中的數據 refererUrl ',this.refererUrl);
            const res = this.tipTool();
            console.log('vue實例的方法 ',res);
          },
          destroyed(){
            //Vue 實例銷燬後調用。調用後,Vue 實例指示的所有東西都會解綁定,所有的事件監聽器會被移除,所有的子實例也會被銷燬
            console.group('vue 生命週期 destroyed');
            console.log('vue實例的el',this.$el);
            console.log('vue實例的data',this.$data);
            console.log('vue實例的data中的數據 message ',this.message);
            console.log('vue實例的data中的數據 refererUrl ',this.refererUrl);
            const res = this.tipTool();
            console.log('vue實例的方法 ',res);
          }
        });
    </script>
</html>

參考文章:1 2

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