1、導航守衛鈎子
導航守衛的用途主要是在用戶離開頁面前提醒用戶,和頁面訪問前先登錄。共有7個鈎子,其中全局鈎子有3個,組件鈎子有3個,路由管道鈎子有1個。
全局鈎子:
const router = new VueRouter({ ... }) router.beforeEach((to, from, next) => { // ...(2) //全局前置守衛 }) router.beforeResolve((to, from, next) => { // ...(6) //全局解析守衛 }) router.afterEach((to, from) => { // ...(7) //全局后置守衛 }
組件內的鈎子:
export default { data(){}, beforeRouteEnter (to, from, next) { //....(5) // 在渲染該組件的對應路由被 confirm 前調用 // 不!能!獲取組件實例 `this` // 因為當守衛執行前,組件實例還沒被創建 }, beforeRouteUpdate (to, from, next) { // ... (3) // 在當前路由改變,但是該組件被復用時調用 // 舉例來說,對於一個帶有動態參數的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉的時候, // 由於會渲染同樣的 Foo 組件,因此組件實例會被復用。而這個鈎子就會在這個情況下被調用。 // 可以訪問組件實例 `this` }, beforeRouteLeave (to, from, next) { // ... (1) // 導航離開該組件的對應路由時調用 // 可以訪問組件實例 `this` } }
路由管道鈎子:
const router = new VueRouter({ routes: [ { path: '/foo', component: Foo, beforeEnter: (to, from, next) => { // ...(4) } } ] })
2、參數解析
每個守衛方法接收三個參數:
-
to: Route
: 即將要進入的目標 路由對象,該對象有目標頁的路由信息。 -
from: Route
: 當前導航正要離開的路由,該對象有當前頁的路由信息。 -
next: Function
: 一定要調用該方法來 resolve 這個鈎子。執行效果依賴next
方法的調用參數。-
next()
: 進行管道中的下一個鈎子。如果全部鈎子執行完了,則導航的狀態就是 confirmed (確認的)。 -
next(false)
: 中斷當前的導航。如果瀏覽器的 URL 改變了 (可能是用戶手動或者瀏覽器后退按鈕),那么 URL 地址會重置到from
路由對應的地址。 -
next('/')
或者next({ path: '/' })
: 跳轉到一個不同的地址。當前的導航被中斷,然后進行一個新的導航。你可以向next
傳遞任意位置對象,且允許設置諸如replace: true
、name: 'home'
之類的選項以及任何用在router-link
的to
prop 或router.push
中的選項。 -
next(error)
: (2.4.0+) 如果傳入next
的參數是一個Error
實例,則導航會被終止且該錯誤會被傳遞給router.onError()
注冊過的回調。
-
確保要調用 next
方法,否則鈎子就不會被 resolved。
3、導航流程
- 導航被觸發。
- 在失活的組件里調用離開守衛。
- 調用全局的
beforeEach
守衛。 - 在重用的組件里調用
beforeRouteUpdate
守衛 (2.2+)。 - 在路由配置里調用
beforeEnter
。 - 解析異步路由組件。
- 在被激活的組件里調用
beforeRouteEnter
。 - 調用全局的
beforeResolve
守衛 (2.5+)。 - 導航被確認。
- 調用全局的
afterEach
鈎子。 - 觸發 DOM 更新。
- 用創建好的實例調用
beforeRouteEnter
守衛中傳給next
的回調函數。
4、導航流程圖(頁面切換的執行順序)
5、頁面跳轉前需登錄 - 實驗
1)首先需要給isLogin為false,表示未登錄,將該值初始在store內,
export default new Vuex.Store({ state: { isLogin: false, }, mutations: { handleLogin(state, login) { state.isLogin = login; }, }, });
2)在登錄頁- 登錄按鈕 設置點擊時修改store內的isLogin為true,同時跳轉到首頁‘/home’
methods: { ...mapMutations(['handleLogin']), handleSubmit() { // 修改store里的isLogin為true,表示登錄了 this.handleLogin(true) this.$router.push({path: '/home'}) } }
3)每一次頁面切換時,全局鈎子beforeEach都會觸發,在該鈎子內判斷 是否登錄了?若沒有登錄,需要跳轉到 登錄頁 ‘/login’,否則 可以跳轉
router.beforeEach((to, from, next) => { const isLogin = obj.state.isLogin; if (to.path === '/login' || isLogin) { next(); } else { next('/login'); } });
6、參考文獻
https://www.cnblogs.com/minigrasshopper/p/7928311.html
route