vue的路由守衛和keep-alive後生命周期詳解
Vue-Router懶加載
1、箭頭函數+import
const List = () => import('@/components/list.vue') const router = new VueRouter({ routes: [ { path: '/list', component: List } ] })
2、箭頭函數+require
const router = new Router({ routes: [ { path: '/list', component: resolve => require(['@/components/list'], resolve) } ] })
如何定義動態路由
param方式
- 配置路由格式:
/router/:id
- 傳遞的方式:在path後面跟上對應的值
- 傳遞後形成的路徑:
/router/123
路由定義
//在APP.vue中 <router-link :to="'/user/'+userId" replace>用戶</router-link> //在index.js { path: '/user/:userid', component: User, },
路由跳轉
// 方法1:<router-link :to="{ name: 'users', params: { myname: jake }}">按鈕</router-link>// 方法2:this.$router.push({name:'users',params:{myname:jake}})// 方法3:this.$router.push// 方法1: <router-link :to="{ name: 'users', params: { myname: jake }}">按鈕</router-link> // 方法2: this.$router.push({name:'users',params:{myname:jake}}) // 方法3: this.$router.push('/user/' + jake)
參數獲取 :通過 $route.params.userid
獲取傳遞的值。
query方式
- 配置路由格式:
/router
,也就是普通配置。 - 傳遞的方式:對象中使用query的key作為傳遞方式。
- 傳遞後形成的路徑:
/route?id=123
。
路由定義
//方式1:直接在router-link 標簽上以對象的形式 <router-link :to="{path:'/profile',query:{name:'why',age:28,height:188}}">檔案</router-link> // 方式2:寫成按鈕以點擊事件形式 <button @click='profileClick'>我的</button> profileClick(){ this.$router.push({ path: "/profile", query: { name: "kobi", age: "28", height: 198 } }); }
跳轉方法
// 方法1: <router-link :to="{ name: 'users', query: { uname: james }}">按鈕</router-link> // 方法2: this.$router.push({ name: 'users', query:{ uname:james }}) // 方法3: <router-link :to="{ path: '/user', query: { uname:james }}">按鈕</router-link> // 方法4: this.$router.push({ path: '/user', query:{ uname:james }}) // 方法5: this.$router.push('/user?uname=' + jsmes)
獲取參數:通過$route.query
獲取傳遞的值
Vue-Router導航守衛
有的時候,需要通過路由來進行一些操作,比如最常見的登錄權限驗證,當用戶滿足條件時,才讓其進入導航,否則就取消跳轉,並跳到登錄頁面讓其登錄。 為此有很多種方法可以植入路由的導航過程:全局的,單個路由獨享的,或者組件級的。
全局路由鉤子
vue-router全局有三個守衛:
router.beforeEach
全局前置守衛 進入路由之前。router.beforeResolve
全局解析守衛,在beforeRouteEnter
調用之後調用。router.afterEach
全局後置鉤子 進入路由之後。
to、from、next這三個參數:
to和from是將要進入和將要離開的路由對象,路由對象指的是平時通過this.$route獲取到的路由對象。next:Function
這個參數是個函數,且必須調用,否則不能進入路由(頁面空白)。
- next() 進入該路由。
- next(false): 取消進入路由,url地址重置為from路由地址(也就是將要離開的路由地址)。
router.beforeEach
router.beforeEach
是全局前置守衛,進入路由之前。
router.beforeEach((to, from, next) => { let ifInfo =Vue.prototype.$common.getSession('userData'); // 判斷是否登錄的存儲信息 if (!ifInfo) { // sessionStorage裡沒有儲存user信息 if (to.path == '/') { //如果是登錄頁面路徑,就直接next() next(); } else { //不然就跳轉到登錄 Message.warning("請重新登錄!"); window.location.href = Vue.prototype.$loginUrl; } } else { return next(); } })
路由獨享守衛
如果你不想全局配置守衛的話,你可以為某些路由單獨配置守衛:
const router = new VueRouter({ routes: [ { path: '/home', component: Home, beforeEnter: (to, from, next) => { // 參數用法什麼的都一樣,調用順序在全局前置守衛後面,所以不會被全局守衛覆蓋 // ... } } ] })
組件內的守衛
beforeRouterEnter
beforeRouterEnter
不能訪問this是因為鉤子在組件實例還沒被創建的時候調用,所以不能獲取組件實例 this,可以通過傳一個回調給next來訪問組件實例 。
beforeRouteEnter (to, from, next) { console.log('在路由獨享守衛後調用'); next(vm => { // 通過 `vm` 訪問組件實例`this` 執行回調的時機在mounted後面, }) }
beforeRouteUpdate
beforeRouteUpdate (to, from, next) { // 在當前路由改變,但是該組件被復用時調用 可以訪問組件實例 `this` // 舉例來說,對於一個帶有動態參數的路徑 /user/:id,在 /user/1 和 /user/2 之間跳轉的時候, // 由於會渲染同樣的 user 組件,因此組件實例會被復用。而這個鉤子就會在這個情況下被調用。 }
beforeRouteLeave
導航離開該組件的對應路由時調用,我們用它來禁止用戶離開,比如還未保存草稿,或者在用戶離開前,將setInterval銷毀,防止離開之後,定時器還在調用。
beforeRouteLeave (to, from , next) { if (文章保存) { next(); // 允許離開或者可以跳到別的路由 上面講過瞭 } else { next(false); // 取消離開 } }
Vue路由鉤子在生命周期函數的體現
完整的路由導航解析流程(不包括其他生命周期):
- 觸發進入其他路由。
- 調用要離開路由的組件守衛
beforeRouteLeave
- 調用全局前置守衛∶
beforeEach
- 在重用的組件裡調用
beforeRouteUpdate
- 調用路由獨享守衛
beforeEnter
。 - 解析異步路由組件。
- 在將要進入的路由組件中調用
beforeRouteEnter
- 調用全局解析守衛
beforeResolve
- 導航被確認。
- 調用全局後置鉤子的
afterEach
鉤子。 - 觸發DOM更新(
mounted
)。 - 執行
beforeRouteEnter
守衛中傳給next
的回調函數。
keep-alive
在開發vue項目中,大部分組件是沒必要多次渲染的,所以vue提供瞭一個內置組件keep-alive
來緩存組件內部狀態,避免重新渲染。
文檔:和 相似, 是一個抽象組件:它自身不會渲染一個 DOM 元素,也不會出現在父組件鏈中。
生命周期鉤子
在被keep-alive
包含的組件/路由中,會多出兩個生命周期的鉤子: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版本之後: Vue新增瞭兩個屬性配合keep-alive來有條件地緩存 路由/組件。
- include:匹配的 路由/組件 會被緩存
- exclude:匹配的 路由/組件 不會被緩存(優先級大)
include和exclude支持三種方式來有條件的緩存路由:采用逗號分隔的字符串形式,正則形式,數組形式。正則和數組形式,必須采用v-bind形式來使用。
<keep-alive include="a,b">//逗號分隔形式 <component :is="view"></component> </keep-alive>
觸發鉤子的完整順序
將路由導航、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。
其實大部分的生命周期鉤子函數不會被用到,但有幾點我們需要註意:
1.ajax請求最好放在created
裡面,此時可以訪問到this,請求返回數據可以放在data裡面。
2.關於dom的操作要放在mounted
裡面,在mounted
前面訪問dom會是undefined,因為還沒渲染完成。
3.每次進入或離開組件需要一些操作時:
- 不緩存
進入的時候可以用created
和mounted
鉤子,離開的時候用beforeDestory
和destroyed
鉤子,beforeDestory
可以訪問this,destroyed
不可以訪問this。
- 緩存瞭的組件:
緩存瞭組件之後,再次進入組件不會觸發beforeCreate、created 、beforeMount、 mounted
,如果你想每次進入組件都做一些事情的話,你可以放在activated
進入緩存組件的鉤子中。同理:離開緩存組件的時候,beforeDestroy和destroyed
並不會觸發,可以使用deactivated
離開緩存組件的鉤子來代替。
總結
本篇文章就到這裡瞭,希望能夠給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!
推薦閱讀:
- vue3緩存頁面keep-alive及路由統一處理詳解
- Vue路由router詳解
- 關於Vue Router的10條高級技巧總結
- vue-router中的鉤子函數和執行順序說明
- 快速理解Vue路由導航守衛