正如其名,vue-router
提供的導航守衛主要用來通過跳轉或取消的方式守衛導航。有多種機會植入路由導航過程中:全局的, 單個路由獨享的, 或者組件級的。
在講解導航守衛前,我們需要理解幾個參數:
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()
注冊過的回調。
一、全局守衛
1.全局前置守衛 router.beforeEach
// 配置路由 const router = new VueRouter({ ... }) //全局守衛的回調函數 router.beforeEach((to, from, next) => { // 這里執行具體操作 // 如果沒有next() 的話將不會進行跳轉 })
這里的 to 是目標路由對象
from 是當前路由對象
next 是執行函數
例子:
// 配置路由 const router = new VueRouter({ routes:[ {path:'/', components:{ //嵌套命名,將component加s default為默認路由 default:Home, theWork1:work1, theWork2:work2, theWork3:work3 }}, {path:'/works',component:Works,name:'WorksLink',redirect:'works/work1', children:[ {path:'work1',component:work1}, {path:'work2',component:work2}, {path:'work3',component:work3} ] }, {path:'/about',component:About}, {path:"*",redirect:'/'} //默認跳轉 ], mode:'history' }) router.beforeEach((to,from,next)=>{ console.log("你想要進行跳轉") })
點擊跳轉,觀察。
這里,我們點擊發現,鈎子已經執行了,由於沒加next()所以不會進行跳轉。
如果你學過ES6的話,你會發現導航守衛和我們的Proxy代理非常相似。
ok,加上next() 就可以正常跳轉。
這個有什么用呢?
當當前訪問的頁面必須登陸的用戶才能訪問,我們就可以使用這個。
在進行 next 跳轉之前,判斷是否登陸,如果沒登陸,就可以 跳轉到登陸界面,讓用戶登陸。
2.全局后置守衛 router.afterEach
按照套路,既然有before 那么很可能就有 after ,全局守衛也有afterEach。
由於,是在跳轉后執行,所以不再接收next參數(我都跳轉了,還要他干嘛!)
router.afterEach((to, from) => { //不接收next函數 // 你想做的事 })
二、 路由獨享的守衛
直接在配置路由是添加 beforeEnter
const router = new VueRouter({ routes: [ { path: '/foo', component: Foo, beforeEnter: (to, from, next) => { // 三個參數和全局守衛一樣 // 僅在該組件上生效,不影響全局守衛 } } ] })
三、組件內的守衛
在組件內使用,如下:
<template> <div> <h1>About</h1> <h3>hi {{name}}</h3> </div> </template> <script> export default { name: 'About', data(){ return { name: 'YoungAm' } }, beforeRouteEnter (to, from, next) { // 在渲染該組件的對應路由被 confirm 前調用 // 不!能!獲取組件實例 `this` // 因為當守衛執行前,組件實例還沒被創建 next(vm=>{ vm.name = "我是新名字" }) }, beforeRouteUpdate (to, from, next) { // 在當前路由改變,但是該組件被復用時調用 // 舉例來說,對於一個帶有動態參數的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉的時候, // 由於會渲染同樣的 Foo 組件,因此組件實例會被復用。而這個鈎子就會在這個情況下被調用。 // 可以訪問組件實例 `this` next() }, beforeRouteLeave (to, from, next) { // 導航離開該組件的對應路由時調用 // 可以訪問組件實例 `this` next() } } </script>
注意,在 beforeRouteEnter 時,組件未被實例化,所以無法訪問this。
在next中添加回調,此時 vm.name 相當於 this.name