Vue父子組件生命周期執行順序

1、vue的生命周期

2、實際操作

下面我們在實際的代碼執行過程中理解父子組件生命周期創建過程以及鉤子函數執行的實時狀態變化。

測試基于下面的代碼,引入vue.js文件后即可執行。(打開頁面后,再按一次刷新會自動進入debugger狀態)

<!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>Document</title>
    <style>
        
    </style>
</head>   
<body>
<div id="app">
    <p>{{message}}</p>
    <keep-alive>
        <my-components :msg="msg1" v-if="show"></my-components>
    </keep-alive>
</div>
</body>
<script src="../../node_modules/vue/dist/vue.js"></script>
<script>
    var child = {
        template: '<div>from child: {{childMsg}}</div>',
        props: ['msg'],
        data: function() {
            return {
                childMsg: 'child'
            }   
        },
        beforeCreate: function () {
            debugger;
        },
        created: function () {
            debugger;
        },
        beforeMount: function () {
            debugger;
        },
        mounted: function () {
            debugger;
        },
        deactivated: function(){
            alert("keepAlive停用");
        },
        activated: function () {
            console.log('component activated');
        },
        beforeDestroy: function () {
            console.group('beforeDestroy 銷毀前狀態===============》');
            var state = {
                'el': this.$el,
                'data': this.$data,
                'message': this.message
            }
            console.log(this.$el);
            console.log(state);
        },
        destroyed: function () {
            console.group('destroyed 銷毀完成狀態===============》');
            var state = {
                'el': this.$el,
                'data': this.$data,
                'message': this.message
            }
            console.log(this.$el);
            console.log(state);
        },
    };
    var vm = new Vue({
        el: '#app',
        data: {
                message: 'father',
                msg1: "hello",
                show: true
            },
        beforeCreate: function () {
            debugger;
        },
        created: function () {
            debugger;
        },
        beforeMount: function () {
            debugger;
        },
        mounted: function () {
            debugger;    
        },
        beforeUpdate: function () {
            alert("頁面視圖更新前");
            
        },
        updated: function () {
            alert("頁面視圖更新后");
        },
        beforeDestroy: function () {
            console.group('beforeDestroy 銷毀前狀態===============》');
            var state = {
                'el': this.$el,
                'data': this.$data,
                'message': this.message
            }
            console.log(this.$el);
            console.log(state);
        },
        destroyed: function () {
            console.group('destroyed 銷毀完成狀態===============》');
            var state = {
                'el': this.$el,
                'data': this.$data,
                'message': this.message
            }
            console.log(this.$el);
            console.log(state);
        },
        components: {
            'my-components': child
        }
    });
</script>
</html>

3.1、生命周期調試

首先我們創建了一個Vue實例vm,將其掛載到頁面中id為“app”的元素上。

3.1.1、根組件的beforeCreate階段

可以看出,在調用beforeCreate()函數時,只進行了一些必要的初始化操作(例如一些全局的配置和根實例的一些屬性初始化),此時data屬性為undefined,沒有可供操作的數據。

3.1.2、根組件的Created階段

調用Created()函數,在這一步,實例已完成以下的配置:數據代理和動態數據綁定(data observer),屬性和方法的運算, watch/event 事件回調。然而,掛載階段還沒開始,$el 屬性目前不可見。

3.1.3、根組件的beforeMount階段

在調用boforeMount()函數前首先會判斷對象是否有el選項。如果有的話就繼續向下編譯,如果沒有el選項,則停止編譯,也就意味著停止了生命周期,直到在該vue實例上調用vm.$mount(el)

在這個例子中,我們有el元素,因此會調用boforeMount()函數,此時已經開始執行模板解析函數,但還沒有將$el元素掛載頁面,頁面視圖因此也未更新。在標紅處,還是 {{message}},這里就是應用的 Virtual DOM(虛擬Dom)技術,先把坑占住了。到后面mounted掛載的時候再把值渲染進去。

3.1.4、子組件的beforeCreate、Created、beforeMount、Mounted階段

在父組件執行beforeMount階段后,進入子組件的beforeCreate、Created、beforeMount階段,這些階段和父組件類似,按下不表。beforeMount階段后,執行的是Mounted階段,該階段時子組件已經掛載到父組件上,并且父組件隨之掛載到頁面中。

由下圖可以知道,在beforeMount階段之后、Mounted階段之前,數據已經被加載到視圖上了,即$el元素被掛載到頁面時觸發了視圖的更新。

3.1.5、子組件的activated階段

我們發現在子父組件全部掛載到頁面之后被觸發。這是因為子組件my-components被<keep-alive> 包裹,隨$el的掛載被觸發。如果子組件沒有被<keep-alive>包裹,那么該階段將不會被觸發。


3.1.6、父組件的mounted階段

mounted執行時:此時el已經渲染完成并掛載到實例上。

至此,從Vue實例的初始化到將新的模板掛載到頁面上的階段已經完成,退出debugger。下面我們來看一下deactivated、beforeUpdate、updated、beforeDestroy、destroyed鉤子函數。

3.2、deactivated、beforeUpdate、updated階段

由生命周期函數可知:當數據變化后、虛擬DOM渲染重新渲染頁面前會觸發beforeUpdate()函數,此時視圖還未改變。當虛擬DOM渲染頁面視圖更新后會觸發updated()函數。

我們不妨改變vm.show = false,當修改這個屬性時,不僅會觸發beforeUpdate、updated函數,還會觸發deactivated函數(因為keep-alive 組件停用時調用)。我們不妨想一下deactivated函數會在beforeUpdate后還是updated后調用。

我們在控制臺輸入vm.show = false。得到三者的調用順序分別為beforeUpdate、deactivated、updated。我們可以知道的是deactivated函數的觸發時間是在視圖更新時觸發。因為當視圖更新時才能知道keep-alive組件被停用了。




3.3、beforeDestroy和destroyed鉤子函數間的生命周期

現在我們對Vue實例進行銷毀,調用app.$destroy()方法即可將其銷毀,控制臺測試如下:



我們發現實例依然存在,但是此時變化已經發生在了其他地方。

beforeDestroy鉤子函數在實例銷毀之前調用。在這一步,實例仍然完全可用。

destroyed鉤子函數在Vue 實例銷毀后調用。調用后,Vue 實例指示的所有東西都會解綁定,所有的事件監聽器會被移除,所有的子實例也會被銷毀(也就是說子組件也會觸發相應的函數)。這里的銷毀并不指代'抹去',而是表示'解綁'。

銷毀時beforeDestory函數的傳遞順序為由父到子,destory的傳遞順序為由子到父。

4、一些應用鉤子函數的想法

  • 在created鉤子中可以對data數據進行操作,這個時候可以進行ajax請求將返回的數據賦給data。

  • 雖然updated函數會在數據變化時被觸發,但卻不能準確的判斷是那個屬性值被改變,所以在實際情況中用computed或match函數來監聽屬性的變化,并做一些其他的操作。

  • 在mounted鉤子對掛載的dom進行操作,此時,DOM已經被渲染到頁面上。

  • 在使用vue-router時有時需要使用<keep-alive></keep-alive>來緩存組件狀態,這個時候created鉤子就不會被重復調用了,如果我們的子組件需要在每次加載或切換狀態的時候進行某些操作,可以使用activated鉤子觸發。

  • 所有的生命周期鉤子自動綁定 this 上下文到實例中,所以不能使用箭頭函數來定義一個生命周期方法 (例如 created: () => this.fetchTodos())。這是導致this指向父級。

5、 小結

  • 加載渲染過程

父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted

  • 子組件更新過程

父beforeUpdate->子beforeUpdate->子updated->父updated

  • 父組件更新過程

父beforeUpdate->父updated

  • 銷毀過程

父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,936評論 6 535
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,744評論 3 421
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,879評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,181評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,935評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,325評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,384評論 3 443
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,534評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,084評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,892評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,067評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,623評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,322評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,735評論 0 27
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,990評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,800評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,084評論 2 375

推薦閱讀更多精彩內容

  • 今天小編給大家詳細講解一下 vue 的生命周期。希望大家多多指教,哪里有遺漏的地方,也請大家指點出來 謝謝。 一、...
    晉飛翔閱讀 1,269評論 0 7
  • 前言 使用Vue在日常開發中會頻繁接觸和使用生命周期,在官方文檔中是這么解釋生命周期的: 每個 Vue 實例在被創...
    心_c2a2閱讀 2,272評論 1 8
  • 前言 接上篇前端Js筆試題面試題,收集整理Vue相關的面試題,供自己現在和以后學習和面試,也希望能對點進來的小伙伴...
    蛙哇閱讀 2,630評論 0 10
  • MVVM MVVM是Model-View-ViewModel的縮寫 Model代表數據模型,可在Model中定義數...
    JunChow520閱讀 759評論 0 0
  • 每個vue實例從創建到銷毀的過程都是一個生命周期,也會運行對應的鉤子函數,下圖為Vue生命周期示意圖: 1.bef...
    yun_154192閱讀 12,653評論 1 7