您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關Vue中鉤子函數有什么用的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
Vue-Router導航守衛
有的時候,我們需要通過路由來進行一些操作,比如最常見的登錄權限驗證,當用戶滿足條件時,才讓其進入導航,否則就取消跳轉,并跳到登錄頁面讓其登錄。
為此我們有很多種方法可以植入路由的導航過程: 全局的, 單個路由獨享的, 或者組件級的 , 推薦優先閱讀官方路由文檔
全局守衛
vue-router全局有三個守衛:
router.beforeEach 全局前置守衛 進入路由之前
router.beforeResolve 全局解析守衛(2.5.0+) 在beforeRouteEnter調用之后調用
router.afterEach 全局后置鉤子 進入路由之后
使用方法:
// main.js 入口文件 import router from './router' ; // 引入路由 router . beforeEach (( to , from , next ) => { next (); }); router . beforeResolve (( to , from , next ) => { next (); }); router . afterEach (( to , from ) => { console . log ( 'afterEach 全局后置鉤子' ); });
to,from,next 這三個參數:
to和from是 將要進入和將要離開的路由對象 ,路由對象指的是平時通過this.$route獲取到的路由對象。
next:Function這個參數是個函數,且 必須調用,否則不能進入路由 (頁面空白)。
next() 進入該路由。
next(false): 取消進入路由,url地址重置為from路由地址(也就是將要離開的路由地址)。
next 跳轉新路由,當前的導航被中斷,重新開始一個新的導航。
我們可以這樣跳轉:next('path地址')
或者 next({path:''})
或者 next({name:''})
且允許設置諸如 replace: true、name: 'home' 之類的選項 以及你用在router-link或router.push的對象選項。
路由獨享守衛
如果你不想全局配置守衛的話,你可以為某些路由單獨配置守衛:
const router = new VueRouter({ routes : [ { path : '/foo' , component : Foo , beforeEnter : ( to , from , next ) => { // ... } } ] })
路由組件內的守衛:
beforeRouteEnter 進入路由前
beforeRouteUpdate (2.2) 路由復用同一個組件時
beforeRouteLeave 離開當前路由時
文檔中的介紹:
beforeRouteEnter (to, from, next) { }, beforeRouteUpdate ( to , from , next ) { // 在當前路由改變,但是該組件被復用時調用 可以訪問組件實例 `this` }, beforeRouteLeave ( to , from , next ) { // 導航離開該組件的對應路由時調用,可以訪問組件實例 `this` }
beforeRouteEnter訪問this
因為鉤子在組件實例還沒被創建的時候調用,所以不能獲取組件實例 this ,可以通過傳一個回調給 next 來訪問組件實例 。
但是 回調的執行時機在mounted后面 ,所以在我看來這里對this的訪問意義不太大,可以放在 created 或者 mounted 里面。
beforeRouteEnter (to, from, next) { console . log ( '在路由獨享守衛后調用' ); next ( vm => { // 通過 `vm` 訪問組件實例`this` 執行回調的時機在mounted后面, }) }
beforeRouteLeave:
導航離開該組件的對應路由時調用,我們用它來禁止用戶離開,比如還未保存草稿,或者在用戶離開前,將 setInterval 銷毀,防止離開之后,定時器還在調用。
beforeRouteLeave (to, from , next) { if ( 文章保存 ) { next (); // 允許離開或者可以跳到別的路由 上面講過了 } else { next ( false ); // 取消離開 } }
關于鉤子的一些知識:
路由鉤子函數的錯誤捕獲
如果我們在全局守衛/路由獨享守衛/組件路由守衛的鉤子函數中有錯誤,可以這樣捕獲:
router.onError(callback => { // 2.4.0新增 并不常用,了解一下就可以了 console . log ( callback , 'callback' ); });
在路由文檔中還有更多的實例方法:動態添加路由等,有興趣可以了解一下。
跳轉死循環,頁面永遠空白
我了解到的,很多人會碰到這個問題,來看一下這段偽代碼:
router.beforeEach((to, from, next) => { if ( 登錄 ){ next () } else { next ({ name : 'login' }); } });
看邏輯貌似是對的,但是當我們跳轉到 login 之后,因為此時還是未登錄狀態,所以會一直跳轉到 login 然后死循環,頁面一直是空白的,所以:我們需要把判斷條件稍微改一下。
if(登錄 || to.name === 'login'){ next() } //
登錄,或者將要前往login頁面的時候,就允許進入路由
全局后置鉤子的跳轉:
文檔中提到因為router.afterEach不接受 next 函數所以也不會改變導航本身,意思就是只能當成一個鉤子來使用,但是我自己在試的時候發現,我們可以通過這種形式來實現跳轉:
// main.js 入口文件 import router from './router' ; // 引入路由 router . afterEach (( to , from ) => { if ( 未登錄 && to . name !== 'login' ) { router . push ({ name : 'login' }); // 跳轉login } });
額,通過router.beforeEach
也完全可以實現且更好,我就騷一下。
完整的路由導航解析流程(不包括其他生命周期):
觸發進入其他路由。
調用要離開路由的組件守衛 beforeRouteLeave
調用局前置守衛: beforeEach
在重用的組件里調用 beforeRouteUpdate
調用路由獨享守衛 beforeEnter 。
解析異步路由組件。
在將要進入的路由組件中調用 beforeRouteEnter
調用全局解析守衛 beforeResolve
導航被確認。
調用全局后置鉤子的 afterEach 鉤子。
觸發DOM更新( mounted )。
執行 beforeRouteEnter 守衛中傳給 next 的回調函數
你不知道的keep-alive[我猜你不知道]
在開發Vue項目的時候,大部分組件是沒必要多次渲染的,所以Vue提供了一個內置組件 keep-alive 來 緩存組件內部狀態,避免重新渲染 。
文檔:和 <transition> 相似, <keep-alive> 是一個抽象組件:它自身不會渲染一個 DOM 元素,也不會出現在父組件鏈中。
用法:
緩存動態組件:
<keep-alive> 包裹動態組件時,會緩存不活動的組件實例,而不是銷毀它們,此種方式并無太大的實用意義。
<!-- 基本 --> < keep - alive > < component : is = "view" ></ component > </ keep - alive > <!-- 多個條件判斷的子組件 --> < keep - alive > < comp - a v - if = "a > 1" ></ comp - a > < comp - b v - else ></ comp - b > </ keep - alive >
緩存路由組件:
使用 keep-alive 可以將所有路徑匹配到的路由組件都緩存起來,包括路由組件里面的組件, keep-alive 大多數使用場景就是這種。
<keep-alive> < router - view ></ router - view > </ keep - alive >
生命周期鉤子:
這篇既然是Vue鉤子函數的專場,那肯定要扣題呀~
在被 keep-alive 包含的組件/路由中,會多出兩個生命周期的鉤子: activated 與 deactivated 。
文檔:在 2.2.0 及其更高版本中,activated 和 deactivated 將會在 樹內的 所有嵌套組件 中觸發。
activated 在組件第一次渲染時會被調用,之后在每次緩存組件被激活時調用。
activated調用時機:
第一次進入緩存路由/組件,在 mounted 后面, beforeRouteEnter 守衛傳給 next 的回調函數之前調用:
beforeMount=> 如果你是從別的路由/組件進來(組件銷毀destroyed/或離開緩存deactivated)=>
mounted=> activated 進入緩存組件 => 執行 beforeRouteEnter回調
因為組件被緩存了,再次進入緩存路由/組件時,不會觸發這些鉤子:
beforeCreate created beforeMount mounted 都不會觸發。
所以之后的調用時機是:
組件銷毀destroyed/或離開緩存deactivated => activated 進入當前緩存組件
=> 執行 beforeRouteEnter回調
組件緩存或銷毀,嵌套組件的銷毀和緩存也在這里觸發
deactivated:組件被停用(離開路由)時調用
使用了keep-alive就不會調用beforeDestroy(組件銷毀前鉤子)和destroyed(組件銷毀),因為組件沒被銷毀,被緩存起來了。
這個鉤子可以看作 beforeDestroy 的替代,如果你緩存了組件,要在組件銷毀的的時候做一些事情,你可以放在這個鉤子里。
如果你離開了路由,會依次觸發:
組件內的離開當前路由鉤子beforeRouteLeave => 路由前置守衛 beforeEach =>
全局后置鉤子afterEach => deactivated 離開緩存組件 => activated 進入緩存組件(如果你進入的也等于是緩存路由)
如果離開的組件沒有緩存的話 beforeDestroy會替換deactivated
如果進入的路由也沒有緩存的話 全局后置鉤子afterEach=>銷毀 destroyed=> beforeCreate等
那么,如果我只是想緩存其中幾個路由/組件,那該怎么做?
緩存你想緩存的路由:
Vue2.1.0之前:
想實現類似的操作,你可以:
配置一下路由元信息
創建兩個 keep-alive 標簽
使用 v-if 通過路由元信息判斷緩存哪些路由。
<keep-alive> < router - view v - if = "$route.meta.keepAlive" > <!-- 這里是會被緩存的路由 --> </ router - view > </ keep - alive > < router - view v - if = "!$route.meta.keepAlive" > <!-- 因為用的是v - if 所以下面還要創建一個未緩存的路由視圖出口 --> </ router - view > //router配置 new Router ({ routes : [ { path : '/' , name : 'home' , component : Home , meta : { keepAlive : true // 需要被緩存 } }, { path : '/:id' , name : 'edit' , component : Edit , meta : { keepAlive : false // 不需要被緩存 } } ] });
Vue2.1.0版本之后:
使用路由元信息的方式,要多創建一個 router-view 標簽,并且每個路由都要配置一個元信息,是可以實現我們想要的效果,但是過于繁瑣了點。
幸運的是在Vue2.1.0之后,Vue新增了兩個屬性配合 keep-alive 來有條件地緩存 路由/組件。
新增屬性:
include :匹配的 路由/組件 會被緩存
exclude :匹配的 路由/組件 不會被緩存
include 和 exclude 支持三種方式來有條件的緩存路由:采用逗號分隔的字符串形式,正則形式,數組形式。
正則和數組形式,必須采用 v-bind 形式來使用。
緩存組件的使用方式:
<!-- 逗號分隔字符串 --> < keep - alive include = "a,b" > < component : is = "view" ></ component > </ keep - alive > <!-- 正則表達式 ( 使用 `v-bind` ) --> < keep - alive : include = "/a|b/" > < component : is = "view" ></ component > </ keep - alive > <!-- 數組 ( 使用 `v-bind` ) --> < keep - alive : include = "['a', 'b']" > < component : is = "view" ></ component > </ keep - alive >
但更多場景中,我們會使用keep-alive來緩存路由:
<keep-alive include='a'> < router - view ></ router - view > </ keep - alive >
匹配規則:
首先匹配組件的name選項,如果 name 選項不可用。
則匹配它的 局部注冊名稱 。 (父組件 components 選項的鍵值)
匿名組件,不可匹配。
比如路由組件沒有 name 選項,并且沒有注冊的組件名。
只能匹配當前被包裹的組件, 不能匹配更下面嵌套的子組件 。
比如用在路由上,只能匹配路由組件的 name 選項,不能匹配路由組件里面的嵌套組件的 name 選項。
文檔: <keep-alive> 不會在函數式組件中正常工作 ,因為它們沒有緩存實例。
exclude 的優先級大于 include
也就是說:當 include 和 exclude 同時存在時, exclude 生效, include 不生效。
<keep-alive include="a,b" exclude="a"> <!-- 只有a不被緩存 --> < router - view ></ router - view > </ keep - alive >
當組件被exclude匹配,該組件將不會被緩存,不會調用activated 和 deactivated。
組件生命周期鉤子:
關于組件的生命周期,是時候放出這張圖片了:
這張圖片已經講得很清楚了,很多人這部分也很清楚了,大部分生命周期并不會用到,這里提一下幾點:
ajax請求最好放在 created 里面 ,因為此時已經可以訪問 this 了,請求到數據就可以直接放在 data 里面。
這里也碰到過幾次,面試官問:ajax請求應該放在哪個生命周期。
關于dom的操作要放在 mounted 里面 ,在 mounted 前面訪問dom會是 undefined 。
每次進入/離開組件都要做一些事情,用什么鉤子:
不緩存:
進入的時候可以用 created 和 mounted 鉤子,離開的時候用 beforeDestory 和 destroyed 鉤子, beforeDestory 可以訪問 this , destroyed 不可以訪問 this 。
緩存了組件:
緩存了組件之后,再次進入組件不會觸發 beforeCreate 、 created 、 beforeMount 、 mounted , 如果你想每次進入組件都做一些事情的話,你可以放在 activated 進入緩存組件的鉤子中 。
同理:離開緩存組件的時候, beforeDestroy 和 destroyed 并不會觸發,可以使用 deactivated 離開緩存組件的鉤子來代替。
觸發鉤子的完整順序:
將路由導航、 keep-alive 、和組件生命周期鉤子結合起來的,觸發順序,假設是從a組件離開,第一次進入b組件:
beforeRouteLeave :路由組件的組件離開路由前鉤子,可取消路由離開。
beforeEach : 路由全局前置守衛,可用于登錄驗證、全局路由loading等。
beforeEnter : 路由獨享守衛
beforeRouteEnter : 路由組件的組件進入路由前鉤子。
beforeResolve : 路由全局解析守衛
afterEach :路由全局后置鉤子
beforeCreate :組件生命周期,不能訪問 this 。
created :組件生命周期,可以訪問 this ,不能訪問dom。
beforeMount :組件生命周期
deactivated : 離開緩存組件a,或者觸發a的 beforeDestroy 和 destroyed 組件銷毀鉤子。
mounted :訪問/操作dom。
activated :進入緩存組件,進入a的嵌套子組件(如果有的話)。
執行beforeRouteEnter回調函數next。
感謝各位的閱讀!關于“Vue中鉤子函數有什么用”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。