Vue Router 3.x 导航守卫基础概念理解
Vue Router 导航守卫(点击查看文章目录)→
导航:表示路由正在发生改变,进行路由跳转
守卫:古代的守门的士兵'守卫',守卫可以通过条件判断路由能不能进行跳转。
三大守卫: 全局守卫,路由独享守卫,组件内守卫。
注意从官网上可知,Vue Router 4.X的版本有不同,next变为可选参数?还没学习到暂时不作讨论,该文章全部为Vue Router 3.x版本的。
1.全局守卫:
项目当中任何路由变化都可以检测到,通过条件判断可不可以进行路由跳转。
举例子:紫禁城【皇帝、太后、妃子】,紫禁城大门守卫全要排查
前置守卫: 路由跳转之前可以做一些事情。
后置守卫: 路由跳转已经完成在执行。
全局解析守卫: 和
router.beforeEach
类似,区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。(不理解区别)全局前置守卫: 在路由跳转完毕之后才会执行一次
全局后置钩子: 不接受第三个参数next,也不会改变导航本身
const router = new VueRouter({ ... }) router.beforeEach((to, from, next) => { // ... })
-
守卫里的三个参数
to: 要跳转到哪个路由(路径)
from: 从哪个路由来的(路径)
next: 放行函数 next()代表放行 next('/path') 或者 next({path:' '}) 放行到指定路由
next(false):中断当前的导航,意思是
确保 next 函数在任何给定的导航守卫中都被严格调用一次。它可以出现多于一次,但是只能在所有的逻辑路径都不重叠的情况下,否则钩子永远都不会被解析或报错
解释:每个导航守卫必须调用next函数一次保证放行。什么时候会出现多次next函数?在路径判断(意味着在不同路径里写响应逻辑),可以出现多次。如果同一路径里调用多次next,这是糟糕的写法会报错或者会无法实现想要的功能。
-
应用场景
前置守卫,很好理解,登录验证控制页面的跳转及重定向。以下是实际业务中验证登录判断路由跳转及重定向。
// 用户登录了才会有token,未登录或者退出登录都没有token let token = store.state.userStore.token // 用户信息 let name = store.state.userStore.userInfo.name // 已经登录 if(token){ if (to.path=='/login'||to.path=='/register') { // 用户已经登录了还想去login,不能去,停留在首页 next('/home') }else{ // 登录,去的不是login // 如果用户名已有不拦 if (name) { next() }else{ // 没有用户信息,派发actions,让仓库存储用户信息在跳转 try { // 获取用户信息成功放行 await store.dispatch('userStore/userInfo') next() } catch (error) { // token失效了 // 清除token失效token await store.dispatch('userStore/quitRegister') // 跳转登录界面,让用户重新登录. ******这里应该是跳转登录界面而不是放行登录界面 next('/login') } } } }else{ // 未登录:不能去交易相关:不能去支付相关【pay,paysuccess】,不能去个人中心 // 未登录去上面这些路由 ----强制登录 let toPath = to.path if(toPath.indexOf('/trade')!=-1 || toPath.indexOf('/pay')!=-1 || toPath.indexOf('/center')!=-1){ // 把未登录的时候想去而没有去成的路径信息,存储于地址栏中【路由】 next('/login?redirect='+toPath); }else{ // 未登录去这些路由(home|search|shopcart) ----放行 next() } }
后置钩子,就是对跳转后的页面进行例如滚动条回调0 0 位置、更新页面title、懒加载结束等等。
router.afterEach((to, from) => { setTitle(to, router.app) iView.LoadingBar.finish() window.scrollTo(0, 0) })
2.路由独享守卫:
【通过什么条件能判断用户登录、未登录】针对某一个路由的守卫
举例子:紫禁城【皇帝、太后、妃子】,是去相应的【皇帝、太子、妃子】寝宫 的路上守卫
用法和全局前置守卫类似,直接使用在路由配置中。
{ name:'pay', path:'/pay', component:()=>import('@/pages/Pay'), meta:{showFooter:true}, // 路由独享守卫 beforeEnter: (to, from, next) => { // ... if (from.path =='/trade') { next() }else{ next(false) } } },
3.组件内守卫:
也是负责某一个路由守卫,直接写在组件内!
举例子:已经到了皇帝寝室外面,是专门负责的守卫
beforeRouteEnter(): 进入该组件路由前 。验证登录判断
beforeRouteUpdate(): 路由更新钩子函数。路由地址没有变化,意味着组件化复用,但是参数变了,如search搜索页面。
beforeRouteLeave(): 离开该组件路由后。这个离开守卫通常用来禁止用户在还未保存修改前突然离开。该导航可以通过
next(false)
来取消。// 组件内守卫,有三个 beforeRouteEnter(to, from, next) { // 在渲染该组件的对应路由被 confirm 前调用 // 不!能!获取组件实例 `this` // 因为当守卫执行前,组件实例还没被创建 if (from.path =='/pay') { next() }else{ next(false) } }, beforeRouteUpdate(to, from, next) { // 在当前路由改变,但是该组件被复用时调用 // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候, // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。 // 可以访问组件实例 `this` }, beforeRouteLeave(to, from, next) { // 导航离开该组件的对应路由时调用 // 可以访问组件实例 `this` }
路由设置
路由模式,滚动行为
let router = new VueRouter({ mode:'hash', // 配置路由,kv一致省略v routes, // 滚动行为 scrollBehavior (to, from, savedPosition) { // return 期望滚动到哪个的位置 // 返回到y=0,滚动条在最上方 return { y: 0 } } })
完整的导航解析流程
- 导航被触发。
- 在失活的组件里调用
beforeRouteLeave
守卫。 - 调用全局的
beforeEach
守卫。 - 在重用的组件里调用
beforeRouteUpdate
守卫 (2.2+)。 - 在路由配置里调用
beforeEnter
。 - 解析异步路由组件。
- 在被激活的组件里调用
beforeRouteEnter
。 - 调用全局的
beforeResolve
守卫 (2.5+)。 - 导航被确认。
- 调用全局的
afterEach
钩子。 - 触发 DOM 更新。调用
beforeRouteEnter
守卫中传给next
的回调函数,创建好的组件实例会作为回调函数的参数传入。
洗尽铅华始见金,褪去浮华归本真