關(guān)于Vue.js2.0生命周期的研究與理解

寫在前面:接觸Vue的時間不多码荔,進行一些項目實踐的時候砸脊,總會涉及到關(guān)于生命周期鉤子或多或少的使用是偷。因此覺得有必要單獨梳理一下相關(guān)的知識點拳氢,如有理解錯誤的地方懇請告知修改。

總體感知

首先貼一張Vue文檔給出的生命周期圖示蛋铆,并添加了一些注釋


lifecycle.fw.png

Vue2.0的生命周期鉤子一共有10個馋评,同樣結(jié)合官方文檔作出了下表

生命周期鉤子 詳細
beforeCreate 在實例初始化之后,數(shù)據(jù)觀測(data observer) 和 event/watcher 事件配置之前被調(diào)用刺啦。
created 實例已經(jīng)創(chuàng)建完成之后被調(diào)用留特。在這一步,實例已完成以下的配置:數(shù)據(jù)觀測(data observer)玛瘸,屬性和方法的運算蜕青, watch/event 事件回調(diào)。然而糊渊,掛載階段還沒開始右核,$el 屬性目前不可見。
beforeMount 在掛載開始之前被調(diào)用:相關(guān)的 render 函數(shù)首次被調(diào)用渺绒。
mounted el 被新創(chuàng)建的 vm.$el 替換贺喝,并掛載到實例上去之后調(diào)用該鉤子。如果 root 實例掛載了一個文檔內(nèi)元素宗兼,當 mounted 被調(diào)用時 vm.$el 也在文檔內(nèi)躏鱼。
beforeUpdate 數(shù)據(jù)更新時調(diào)用,發(fā)生在虛擬 DOM 重新渲染和打補丁之前殷绍。你可以在這個鉤子中進一步地更改狀態(tài)染苛,這不會觸發(fā)附加的重渲染過程。
updated 由于數(shù)據(jù)更改導(dǎo)致的虛擬 DOM 重新渲染和打補丁主到,在這之后會調(diào)用該鉤子茶行。當這個鉤子被調(diào)用時贸呢,組件 DOM 已經(jīng)更新,所以你現(xiàn)在可以執(zhí)行依賴于 DOM 的操作拢军。
activated keep-alive 組件激活時調(diào)用楞陷。
deactivated keep-alive 組件停用時調(diào)用。
beforeDestroy 實例銷毀之前調(diào)用茉唉。在這一步固蛾,實例仍然完全可用。
destroyed Vue 實例銷毀后調(diào)用度陆。調(diào)用后艾凯,Vue 實例指示的所有東西都會解綁定,所有的事件監(jiān)聽器會被移除懂傀,所有的子實例也會被銷毀趾诗。

(除了beforeCreate和created鉤子之外,其他鉤子均在服務(wù)器端渲染期間不被調(diào)用蹬蚁。)

實際操作

我們來可視化的觀察一下生命周期鉤子函數(shù)執(zhí)行時狀態(tài)變化的情況

測試過程基于以下代碼執(zhí)行恃泪,引入vue.js后可直接執(zhí)行

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./vue.js"></script>
</head>
<body>
<div id="app">
    <p>{{message}}</p>
    <keep-alive>
        <my-components msg="hello" v-if="show"></my-components>
    </keep-alive>
</div>
</body>
<script>
    var child = {
        template: '<div>from child: {{msg}}</div>',
        props: ['msg'],
        data: function () {
            return {
                childMsg: 'child'
            };
        },
        deactivated: function () {
            console.log('component deactivated!');
        },
        activated: function () {
            console.log('component activated');
        }
    };
    var app = new Vue({
        el: '#app',
        data: function () {
            return {
                message: 'father',
                show: true
            };
        },
        beforeCreate: function () {
            console.group('beforeCreate 創(chuàng)建前狀態(tài)===============》');
            var state = {
                'el': this.$el,
                'data': this.$data,
                'message': this.message
            }
            console.log(state);
        },
        created: function () {
            console.group('created 創(chuàng)建完畢狀態(tài)===============》');
            var state = {
                'el': this.$el,
                'data': this.$data,
                'message': this.message
            }
            console.log(state);
        },
        beforeMount: function () {
            console.group('beforeMount 掛載前狀態(tài)===============》');
            var state = {
                'el': this.$el,
                'data': this.$data,
                'message': this.message
            }
            console.log(this.$el);
            console.log(state);
        },
        mounted: function () {
            console.group('mounted 掛載結(jié)束狀態(tài)===============》');
            var state = {
                'el': this.$el,
                'data': this.$data,
                'message': this.message
            }
            console.log(this.$el);
            console.log(state);
            // this.message = 'change';
        },
        beforeUpdate: function () {
            console.group('beforeUpdate 更新前狀態(tài)===============》');
            var state = {
                'el': this.$el,
                'data': this.$data,
                'message': this.message
            }
            console.log(this.$el);
            console.log(state);
            // this.message = 'change2';
        },
        updated: function () {
            console.group('updated 更新完成狀態(tài)===============》');
            var state = {
                'el': this.$el,
                'data': this.$data,
                'message': this.message
            }
            console.log(this.$el);
            console.log(state);
        },
        beforeDestroy: function () {
            console.group('beforeDestroy 銷毀前狀態(tài)===============》');
            var state = {
                'el': this.$el,
                'data': this.$data,
                'message': this.message
            }
            console.log(this.$el);
            console.log(state);
        },
        destroyed: function () {
            console.group('destroyed 銷毀完成狀態(tài)===============》');
            var state = {
                'el': this.$el,
                'data': this.$data,
                'message': this.message
            }
            console.log(this.$el);
            console.log(state);
        },
        components: {
            'my-components': child
        }
    });
</script>
</html>

首先來梳理一下結(jié)構(gòu):
1.我們創(chuàng)建了一個Vue根實例命名為app,將其掛載到頁面id為app的dom元素上犀斋。
2.局部注冊的一個組件child并在根實例中將其注冊使其可以在根實例的作用域中使用贝乎。
3.將子組件用<keep-alive> 包裹,為接下來的測試作準備叽粹。
在谷歌瀏覽器打開開發(fā)者工具览效,開始測試!

create 和 mounted 相關(guān)

測試效果圖如下:


test1.jpg

根據(jù)測試結(jié)果虫几,可以看出

1.beforeCreate執(zhí)行時:data和el均未初始化锤灿,值為undefined
2.created執(zhí)行時:Vue 實例觀察的數(shù)據(jù)對象data已經(jīng)配置好,已經(jīng)可以得到app.message的值辆脸,但Vue 實例使用的根 DOM 元素el還未初始化
3.beforeMount執(zhí)行時:data和el均已經(jīng)初始化但校,但從{{message}}等現(xiàn)象可以看出此時el并沒有渲染進數(shù)據(jù),el的值為“虛擬”的元素節(jié)點
4.mounted執(zhí)行時:此時el已經(jīng)渲染完成并掛載到實例上

activated 和 destroyed相關(guān)

在前面的測試圖中每强,我們發(fā)現(xiàn)了activated周期鉤子已經(jīng)被觸發(fā)始腾,這是因為子組件my-components被<keep-alive> 包裹,隨el的掛載觸發(fā)空执。
??現(xiàn)在我們將此組件停用進行測試:由于子組件具有一個v-if指令v-if="show",因此我們可以通過將show的值置為false將其銷毀穗椅。
??控制臺輸入 app.show = false;測試結(jié)果如下:


test2.jpg

由于在這里我們修改了data的值辨绊,所以會觸發(fā)beforeUpdate和updated鉤子,這里先不討論這一組鉤子匹表,我們看到deactivated鉤子已經(jīng)觸發(fā)门坷,表示<keep-alive>已經(jīng)停用宣鄙,符合預(yù)期結(jié)果。

現(xiàn)在我們對Vue實例進行銷毀默蚌,調(diào)用app.$destroy()方法即可將其銷毀冻晤,控制臺測試如下:


test3.jpg

我們發(fā)現(xiàn)實例依然存在,但是此時變化已經(jīng)發(fā)生在了其他地方绸吸,根據(jù)官方文檔描述:Vue 實例指示的所有東西都會解綁定鼻弧,所有的事件監(jiān)聽器會被移除,所有的子實例也會被銷毀锦茁。

繼續(xù)測試攘轩,現(xiàn)在修改 data中的數(shù)據(jù)查看結(jié)果,如下:


test4.jpg

這里我們將data中的message屬性改成了'world'码俩,發(fā)現(xiàn)dom并沒有進行相應(yīng)的響應(yīng)度帮,這證實了之前的說法。同樣稿存,如果你在子組件也加入destroyed鉤子笨篷,發(fā)現(xiàn)該鉤子也會被觸發(fā),這也證明了子實例也會被一起銷毀瓣履。這里的銷毀并不指代'抹去'冕屯,而是表示'解綁'。

updated相關(guān)

beforeUpdate和updated是最后一對周期鉤子了拂苹。
為了能看出測試的具體效果安聘,我們需要在原來的代碼上添加兩行代碼:

在c鉤子和updated鉤子中分別加上
console.log('beforeUpdate == ' + document.getElementsByTagName('p')[0].innerHTML);

控制臺輸入app.message = 'abc';效果如下:


test5.jpg

我們發(fā)現(xiàn)beforeUpdate和updated觸發(fā)時,el中的數(shù)據(jù)都已經(jīng)渲染完成瓢棒,但根據(jù)beforeUpdate == father而updated == abc可知浴韭,只有updated鉤子被調(diào)用時候,組件dom才被更新脯宿。

結(jié)尾

到這里已經(jīng)總結(jié)完成了念颈,感覺只有理解的生命周期鉤子的使用,才能更好配合其他方法事件使用连霉。如果您發(fā)現(xiàn)錯誤的地方榴芳,請告訴我及時修改,謝謝跺撼!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末窟感,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子歉井,更是在濱河造成了極大的恐慌柿祈,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,744評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異躏嚎,居然都是意外死亡蜜自,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評論 3 392
  • 文/潘曉璐 我一進店門卢佣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來重荠,“玉大人,你說我怎么就攤上這事虚茶「曷常” “怎么了?”我有些...
    開封第一講書人閱讀 163,105評論 0 353
  • 文/不壞的土叔 我叫張陵媳危,是天一觀的道長荞彼。 經(jīng)常有香客問我,道長待笑,這世上最難降的妖魔是什么鸣皂? 我笑而不...
    開封第一講書人閱讀 58,242評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮暮蹂,結(jié)果婚禮上寞缝,老公的妹妹穿的比我還像新娘。我一直安慰自己仰泻,他們只是感情好荆陆,可當我...
    茶點故事閱讀 67,269評論 6 389
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著集侯,像睡著了一般被啼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上棠枉,一...
    開封第一講書人閱讀 51,215評論 1 299
  • 那天浓体,我揣著相機與錄音,去河邊找鬼辈讶。 笑死命浴,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的贱除。 我是一名探鬼主播生闲,決...
    沈念sama閱讀 40,096評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼月幌!你這毒婦竟也來了碍讯?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,939評論 0 274
  • 序言:老撾萬榮一對情侶失蹤飞醉,失蹤者是張志新(化名)和其女友劉穎冲茸,沒想到半個月后屯阀,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體缅帘,經(jīng)...
    沈念sama閱讀 45,354評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡轴术,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,573評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了钦无。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逗栽。...
    茶點故事閱讀 39,745評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖失暂,靈堂內(nèi)的尸體忽然破棺而出彼宠,到底是詐尸還是另有隱情,我是刑警寧澤弟塞,帶...
    沈念sama閱讀 35,448評論 5 344
  • 正文 年R本政府宣布凭峡,位于F島的核電站,受9級特大地震影響决记,放射性物質(zhì)發(fā)生泄漏摧冀。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,048評論 3 327
  • 文/蒙蒙 一系宫、第九天 我趴在偏房一處隱蔽的房頂上張望索昂。 院中可真熱鬧,春花似錦扩借、人聲如沸椒惨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽康谆。三九已至,卻和暖如春嫉到,著一層夾襖步出監(jiān)牢的瞬間沃暗,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評論 1 269
  • 我被黑心中介騙來泰國打工屯碴, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留描睦,地道東北人。 一個月前我還...
    沈念sama閱讀 47,776評論 2 369
  • 正文 我出身青樓导而,卻偏偏與公主長得像忱叭,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子今艺,可洞房花燭夜當晚...
    茶點故事閱讀 44,652評論 2 354

推薦閱讀更多精彩內(nèi)容