詳解Vue的鉤子函數(shù)(路由導航守衛(wèi)端盆、keep-alive、生命周期鉤子)

前言

說到Vue的鉤子函數(shù)费封,可能很多人只停留在一些很簡單常用的鉤子(created,mounted)焕妙,而且對于里面的區(qū)別,什么時候該用什么鉤子弓摘,并沒有仔細的去研究過焚鹊,且Vue的生命周期在面試中也算是比較高頻的考點,那么該如何回答這類問題韧献,讓人有眼前一亮的感覺呢...

Vue-Router導航守衛(wèi):

有的時候末患,我們需要通過路由來進行一些操作,比如最常見的登錄權限驗證锤窑,當用戶滿足條件時璧针,才讓其進入導航,否則就取消跳轉(zhuǎn)渊啰,并跳到登錄頁面讓其登錄探橱。

為此我們有很多種方法可以植入路由的導航過程:全局的, 單個路由獨享的, 或者組件級的,推薦優(yōu)先閱讀路由文檔

全局守衛(wèi)

vue-router全局有三個守衛(wèi):

\bullet router.beforeEach 全局前置守衛(wèi) 進入路由之前

\bullet router.beforeResolve 全局解析守衛(wèi)(2.5.0+) 在beforeRouteEnter調(diào)用之后調(diào)用

\bullet router.afterEach 全局后置鉤子 進入路由之后

使用方法:

to,from,next 這三個參數(shù):

to和from是將要進入和將要離開的路由對象,路由對象指的是平時通過this.$route獲取到的路由對象。

\bullet next:Function 這個參數(shù)是個函數(shù)绘证,且必須調(diào)用走搁,否則不能進入路由(頁面空白)。

\bullet next() 進入該路由迈窟。

\bullet next(false): 取消進入路由私植,url地址重置為from路由地址(也就是將要離開的路由地址)。

\bullet next 跳轉(zhuǎn)新路由车酣,當前的導航被中斷曲稼,重新開始一個新的導航索绪。

我們可以這樣跳轉(zhuǎn):next('path地址')或者next({path:''})或者next({name:''})

且允許設置諸如 replace: true、name: 'home' 之類的選項

以及你用在router-link或router.push的對象選項贫悄。

路由獨享守衛(wèi)

如果你不想全局配置守衛(wèi)的話瑞驱,你可以為某些路由單獨配置守衛(wèi):

路由組件內(nèi)的守衛(wèi):

\bullet beforeRouteEnter 進入路由前

\bullet beforeRouteUpdate (2.2) 路由復用同一個組件時

\bullet beforeRouteLeave 離開當前路由時

文檔中的介紹:


beforeRouteEnter訪問this

因為鉤子在組件實例還沒被創(chuàng)建的時候調(diào)用,所以不能獲取組件實例 this窄坦,可以通過傳一個回調(diào)給next來訪問組件實例唤反。

但是回調(diào)的執(zhí)行時機在mounted后面,所以在我看來這里對this的訪問意義不太大,可以放在created或者mounted里面鸭津。

beforeRouteLeave:

導航離開該組件的對應路由時調(diào)用彤侍,我們用它來禁止用戶離開,比如還未保存草稿逆趋,或者在用戶離開前盏阶,將setInterval銷毀,防止離開之后闻书,定時器還在調(diào)用名斟。

關于鉤子的一些知識:

路由鉤子函數(shù)的錯誤捕獲

如果我們在全局守衛(wèi)/路由獨享守衛(wèi)/組件路由守衛(wèi)的鉤子函數(shù)中有錯誤,可以這樣捕獲:


在路由文檔中還有更多的實例方法:動態(tài)添加路由等魄眉,有興趣可以了解一下砰盐。

跳轉(zhuǎn)死循環(huán),頁面永遠空白

我了解到的坑律,很多人會碰到這個問題楞卡,來看一下這段偽代碼:


看邏輯貌似是對的,但是當我們跳轉(zhuǎn)到login之后脾歇,因為此時還是未登錄狀態(tài)蒋腮,所以會一直跳轉(zhuǎn)到login然后死循環(huán),頁面一直是空白的藕各,所以:我們需要把判斷條件稍微改一下池摧。

全局后置鉤子的跳轉(zhuǎn):

文檔中提到因為router.afterEach不接受next函數(shù)所以也不會改變導航本身,意思就是只能當成一個鉤子來使用激况,但是我自己在試的時候發(fā)現(xiàn)作彤,我們可以通過這種形式來實現(xiàn)跳轉(zhuǎn):


額,通過router.beforeEach 也完全可以實現(xiàn)且更好乌逐,我就騷一下竭讳。

完整的路由導航解析流程(不包括其他生命周期):

\bullet 觸發(fā)進入其他路由。

\bullet 調(diào)用要離開路由的組件守衛(wèi)beforeRouteLeave

\bullet 調(diào)用局前置守衛(wèi):beforeEach

\bullet 在重用的組件里調(diào)用beforeRouteUpdate

\bullet 調(diào)用路由獨享守衛(wèi)beforeEnter浙踢。

\bullet 解析異步路由組件绢慢。

\bullet 在將要進入的路由組件中調(diào)用beforeRouteEnter

\bullet 調(diào)用全局解析守衛(wèi)beforeResolve

\bullet 導航被確認。

\bullet 調(diào)用全局后置鉤子的afterEach 鉤子洛波。

\bullet 觸發(fā)DOM更新(mounted)胰舆。

\bullet 執(zhí)行beforeRouteEnter 守衛(wèi)中傳給 next 的回調(diào)函數(shù)

你不知道的keep-alive[我猜你不知道]

在開發(fā)Vue項目的時候骚露,大部分組件是沒必要多次渲染的,所以Vue提供了一個內(nèi)置組件keep-alive來緩存組件內(nèi)部狀態(tài)缚窿,避免重新渲染棘幸,keep-alive

文檔:和 <transition>相似,<keep-alive> 是一個抽象組件:它自身不會渲染一個 DOM 元素倦零,也不會出現(xiàn)在父組件鏈中误续。

用法:

緩存動態(tài)組件:

緩存路由組件:

使用keep-alive可以將所有路徑匹配到的路由組件都緩存起來,包括路由組件里面的組件扫茅,keep-alive大多數(shù)使用場景就是這種蹋嵌。

生命周期鉤子:

這篇既然是Vue鉤子函數(shù)的專場,那肯定要扣題呀~

在被keep-alive包含的組件/路由中诞帐,會多出兩個生命周期的鉤子:activated與 deactivated欣尼。

文檔:在 2.2.0 及其更高版本中爆雹,activated 和 deactivated 將會在? 樹內(nèi)的所有嵌套組件中觸發(fā)停蕉。

activated在組件第一次渲染時會被調(diào)用,之后在每次緩存組件被激活時調(diào)用钙态。

activated調(diào)用時機:

第一次進入緩存路由/組件慧起,在mounted后面,beforeRouteEnter守衛(wèi)傳給 next 的回調(diào)函數(shù)之前調(diào)用:

beforeMount=> 如果你是從別的路由/組件進來(組件銷毀destroyed/或離開緩存deactivated)=>mounted=> activated 進入緩存組件 => 執(zhí)行 beforeRouteEnter回調(diào)

因為組件被緩存了册倒,再次進入緩存路由/組件時蚓挤,不會觸發(fā)這些鉤子:

// beforeCreate created beforeMount mounted 都不會觸發(fā)。

所以之后的調(diào)用時機是:

組件銷毀destroyed/或離開緩存deactivated => activated 進入當前緩存組件?=> 執(zhí)行 beforeRouteEnter回調(diào)

? // 組件緩存或銷毀驻子,嵌套組件的銷毀和緩存也在這里觸發(fā)

deactivated:組件被停用(離開路由)時調(diào)用

使用了keep-alive就不會調(diào)用beforeDestroy(組件銷毀前鉤子)和destroyed(組件銷毀)灿意,因為組件沒被銷毀,被緩存起來了崇呵。

這個鉤子可以看作beforeDestroy的替代缤剧,如果你緩存了組件,要在組件銷毀的的時候做一些事情域慷,你可以放在這個鉤子里荒辕。

如果你離開了路由,會依次觸發(fā):

組件內(nèi)的離開當前路由鉤子beforeRouteLeave =>? 路由前置守衛(wèi) beforeEach =>全局后置鉤子afterEach => deactivated 離開緩存組件 => activated 進入緩存組件(如果你進入的也是緩存路由)

如果離開的組件沒有緩存的話 beforeDestroy會替換deactivated

如果進入的路由也沒有緩存的話? 全局后置鉤子afterEach=>銷毀 destroyed=> beforeCreate等

那么犹褒,如果我只是想緩存其中幾個路由/組件抵窒,那該怎么做?

緩存你想緩存的路由:

Vue2.1.0之前:

想實現(xiàn)類似的操作叠骑,你可以:

配置一下路由元信息

創(chuàng)建兩個keep-alive標簽

使用v-if通過路由元信息判斷緩存哪些路由李皇。

Vue2.1.0版本之后:

使用路由元信息的方式,要多創(chuàng)建一個router-view標簽宙枷,并且每個路由都要配置一個元信息疙赠,是可以實現(xiàn)我們想要的效果付材,但是過于繁瑣了點。

幸運的是在Vue2.1.0之后圃阳,Vue新增了兩個屬性配合keep-alive來有條件地緩存 路由/組件厌衔。

新增屬性:

include:匹配的 路由/組件 會被緩存

exclude:匹配的 路由/組件 不會被緩存

include和exclude支持三種方式來有條件的緩存路由:采用逗號分隔的字符串形式,正則形式捍岳,數(shù)組形式富寿。

正則和數(shù)組形式,必須采用v-bind形式來使用锣夹。

緩存組件的使用方式:

但更多場景中页徐,我們會使用keep-alive來緩存路由:

匹配規(guī)則:

1、首先匹配組件的name選項银萍,如果name選項不可用变勇。

2、則匹配它的局部注冊名稱贴唇。 (父組件 components 選項的鍵值)

3搀绣、匿名組件,不可匹配戳气。

比如路由組件沒有name選項链患,并且沒有注冊的組件名。

4瓶您、只能匹配當前被包裹的組件麻捻,不能匹配更下面嵌套的子組件。

比如用在路由上呀袱,只能匹配路由組件的name選項贸毕,不能匹配路由組件里面的嵌套組件的name選項。

5夜赵、文檔:不會在函數(shù)式組件中正常工作明棍,因為它們沒有緩存實例。

6油吭、exclude的優(yōu)先級大于include

也就是說:當include和exclude同時存在時击蹲,exclude生效,include不生效婉宰。


當組件被exclude匹配歌豺,該組件將不會被緩存,不會調(diào)用activated 和 deactivated心包。

組件生命周期鉤子:

關于組件的生命周期类咧,是時候放出這張圖片了:


這張圖片已經(jīng)講得很\bullet 清楚了,很多人這部分也很清楚了,大部分生命周期并不會用到痕惋,這里提一下幾點:

\bullet ajax請求最好放在created里面区宇,因為此時已經(jīng)可以訪問this了,請求到數(shù)據(jù)就可以直接放在data里面值戳。這里也碰到過幾次议谷,面試官問:ajax請求應該放在哪個生命周期。

\bullet 關于dom的操作要放在mounted里面堕虹,在mounted前面訪問dom會是undefined卧晓。

\bullet 每次進入/離開組件都要做一些事情,用什么鉤子:

不緩存:

進入的時候可以用created和mounted鉤子赴捞,離開的時候用beforeDestory和destroyed鉤子,beforeDestory可以訪問this逼裆,destroyed不可以訪問this。

緩存了組件:

緩存了組件之后赦政,再次進入組件不會觸發(fā)beforeCreate胜宇、created 、beforeMount恢着、 mounted桐愉,如果你想每次進入組件都做一些事情的話,你可以放在activated進入緩存組件的鉤子中然评。

同理:離開緩存組件的時候仅财,beforeDestroy和destroyed并不會觸發(fā)狈究,可以使用deactivated離開緩存組件的鉤子來代替碗淌。

觸發(fā)鉤子的完整順序:

將路由導航、keep-alive抖锥、和組件生命周期鉤子結(jié)合起來的亿眠,觸發(fā)順序,假設是從a組件離開磅废,第一次進入b組件:

\bullet beforeRouteLeave:路由組件的組件離開路由前鉤子纳像,可取消路由離開。

\bullet beforeEach: 路由全局前置守衛(wèi)拯勉,可用于登錄驗證竟趾、全局路由loading等。

\bullet beforeEnter: 路由獨享守衛(wèi)

\bullet beforeRouteEnter: 路由組件的組件進入路由前鉤子宫峦。

\bullet beforeResolve:路由全局解析守衛(wèi)

\bullet afterEach:路由全局后置鉤子

\bullet beforeCreate:組件生命周期岔帽,不能訪問this。

\bullet created:組件生命周期导绷,可以訪問this,不能訪問dom。

\bullet beforeMount:組件生命周期

\bullet deactivated: 離開緩存組件a蛤高,或者觸發(fā)a的beforeDestroy和destroyed組件銷毀鉤子。

\bullet mounted:訪問/操作dom钦购。

\bullet activated:進入緩存組件,進入a的嵌套子組件(如果有的話)褂萧。

\bullet 執(zhí)行beforeRouteEnter回調(diào)函數(shù)next押桃。

結(jié)語

Vue提供了很多鉤子,但很多鉤子我們幾乎不會用到导犹,只有清楚這些鉤子函數(shù)的觸發(fā)順序以及背后的一些限制等怨规,這樣我們才能夠正確的使用這些鉤子,希望看了本文的同學锡足,能對這些鉤子有更加清晰的認識波丰,使用起來更加得心應手。

原文檔

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末舶得,一起剝皮案震驚了整個濱河市掰烟,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌沐批,老刑警劉巖纫骑,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異九孩,居然都是意外死亡先馆,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進店門躺彬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來煤墙,“玉大人,你說我怎么就攤上這事宪拥》乱埃” “怎么了?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵她君,是天一觀的道長脚作。 經(jīng)常有香客問我,道長缔刹,這世上最難降的妖魔是什么球涛? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮校镐,結(jié)果婚禮上亿扁,老公的妹妹穿的比我還像新娘。我一直安慰自己灭翔,他們只是感情好魏烫,可當我...
    茶點故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布辣苏。 她就那樣靜靜地躺著,像睡著了一般哄褒。 火紅的嫁衣襯著肌膚如雪稀蟋。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天呐赡,我揣著相機與錄音退客,去河邊找鬼。 笑死链嘀,一個胖子當著我的面吹牛萌狂,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播怀泊,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼茫藏,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了霹琼?” 一聲冷哼從身側(cè)響起务傲,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎枣申,沒想到半個月后售葡,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡忠藤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年挟伙,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片模孩。...
    茶點故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡尖阔,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瓜贾,到底是詐尸還是另有隱情诺祸,我是刑警寧澤携悯,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布祭芦,位于F島的核電站,受9級特大地震影響憔鬼,放射性物質(zhì)發(fā)生泄漏龟劲。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一轴或、第九天 我趴在偏房一處隱蔽的房頂上張望昌跌。 院中可真熱鬧,春花似錦照雁、人聲如沸蚕愤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽萍诱。三九已至悬嗓,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間裕坊,已是汗流浹背包竹。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留籍凝,地道東北人周瞎。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像饵蒂,于是被迫代替她去往敵國和親声诸。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,781評論 2 354