[vue]vue-router导航守卫

133 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第 18 天,点击查看活动详情

导航守卫

如果在路由跳转过程中,想要改变跳转地址或取消跳转时,就要用到导航守卫了。

守卫分为:全局守卫, 单个路由独享的, 或者组件级的

全局守卫

1、beforeEach

全局前置守卫
所有路由都会经过它把关,在这里可以拦截处理用户是否有访问页面的权限

接收三个参数:

  • to: 目标路由对象,即到哪里去
  • from: 当前导航正要离开的路由,即从哪里来
  • next: 必须要有的,一定要调用该方法来 resolve 这个钩子。
    1. next(), 通过当前导航,进行管道中的下一个钩子
    2. next(false),中断当前的导航
    3. next('/') 或者 next({ path: '/' }),当前的导航被中断,然后进行一个新的导航。
    4. next(error),传入一个Error实例,导航终止,错误信息会传递给 router.onError()的回调
const router = new VueRouter({
  routes: [
    { 
        path: '/about', 
        meta: { auth: true },
        component: () => import('../views/about.vue'),
    },
  ]
})
// 在定义路由的时候配置了meta字段(路由元信息)
router.beforeEach((to, from, next) => {
    // 路由是否需要守卫,用户是否有页面权限
  if (to.meta.auth) { 
    // 是否登录
    if (window.isLogin) { 
        // 如果登录了就放路由通行
        next() 
    } else { 
        // 没有登录时,终止当前导航,跳转到新的页面(登录页面),同时设置了redirect:登录后应该显示的页面地址
        next('/login?redirect='+to.fullPath) 
    } 
  } else { 
  // 无需守卫,即任何人都可以访问的页面,不需要控制页面权限的页面
    next() 
  }
})

<template> 
    <div> 
        <button @click="login" v-if="!isLogin">登录</button> 
        <button @click="logout" v-else>退出</button> 
    </div> 
</template> 
<script> 
export default { 
    methods: { 
        login() { 
            window.isLogin = true 
            this.$router.push(this.$route.query.redirect) 
            
        },
        logout() { 
            window.isLogin = false 
        } },
        computed: { 
            isLogin() { 
                return window.isLogin 
            } 
        }
} 
</script>

2、beforeResolve

全局解析守卫

参数:beforeResolve(to, from, next)

使用同beforeEach(to, from, next)类似;
区别在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后调用

3、afterEach

全局后置钩子\

路由跳转后的钩子,不会改变导航,不需要next 参数:afterEach((to, from)

路由独享的守卫

1、beforeEnter

路由独享的守卫

可以在路由配置上直接定义 beforeEnter 守卫; 不常用

参数:beforeEnter(to, from, next)

const router = new VueRouter({
  routes: [
    {
      path: '/about', name: 'about',
      component: () => import('../views/about.vue'),
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})

组件内守卫

5、beforeRouteEnter

beforeRouteEnter(to, from, next) {
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`
    // 因为当守卫执行前,组件实例还没被创建
    next(vm => {
        // 通过 `vm` 访问组件实例
    })
},

6、beforeRouteUpdate

beforeRouteUpdate(to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
},

使用动态路径参数时,处理通过watch $route的方式监听路由还可以通过beforeRouteUpdate钩子

7、beforeRouteLeave

beforeRouteLeave(to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例 `this`
}

小结

  • 离开组件:beforeRouteLeave
  • 全局组件拦截:beforeEach
  • 在路由配置里调用 beforeEnter
  • 进入组件内,组件激活:beforeRouteEnter
  • 调用全局解析守卫:beforeResolve
  • 路由跳转完后,调用全局后置守卫:afterEach
  • 组件参数更新:beforeRouteUpdate