1、全局守卫

在项目开发中每一次路由的切换或者页面的刷新都需要判断用户是否已经登录,前端可以判断,后端也会进行判断的,我们前端最好也进行判断。

vue-router提供了导航钩子:全局前置导航钩子 beforeEach和全局后置导航钩子 afterEach,他们会在路由即将改变前和改变后进行触发。所以判断用户是否登录需要在beforeEach导航钩子中进行判断。

vue-router官方解释 导航”表示路由正在发生改变。 vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。
理解: 导航守卫可以看做是 vue-router 的生命周期钩子 假设用户要查看个人信息(用户直接输入url进入个人信息页面) 如果没登陆是不是不让获取用户信息 但是用户已经进入了个人信息页面 这个导航守卫呢 就是帮助开发者处理这种事件

导航守卫的功能 根据判断条件处理地址栏的变化
导航守卫分为:全局的、单个路由独享的、组件内的三种。

【全局的】:是指路由实例上直接操作的钩子函数,他的特点是所有路由配置的组件都会触发,直白点就是触发路由就会触发这些钩子函数.
只要加了全局守卫,每次路由的跳转都要经过全局守卫,一般是用的都是前置守卫

全局前置守卫

beforeEach在路由跳转前触发,参数包括to,from,next(参数会单独介绍)三个,这个钩子作用主要是用于登录验证,也就是路由还没跳转提前告知,以免跳转了再通知就为时已晚

与之前的使用都一样,没有任何变化。

router.beforeEach((to, from, next) => { 
    // 里面三个参数  to代表我们将要跳转的路径
    // from 代表从那个路径跳转过来 就是上一个路径
    // next代表 守卫可以通过next控制下一步的跳转 如果写了前置守卫 一定要添加next()到下一步 
    // 因为路由还没有跳转 next可以是路由跳转
    // 需要注意的是 如果当跳转的地址带参数的时候(动态路由) 跳转的时候就会忽略后面传递的参数 
    // 如 next({path:"/user",params:{id:1}})
    // 解决方法 换一种写法
    // next("/user/1") 或用命名路由的方式跳转next({name:"user",params:{id:1}})
  // ...
})

全局前置守卫应用场景(进入页面登录判断、管理员权限判断、浏览器判断等)

比如我们的后台管理系统,只有在登录的情况下才能进行访问,没有登录情况下即使通过路由去访问也会被重定向到登录页面

router.beforeEach((to, from,next) => { 
    //改变每个路由标题
  document.title = to.meta.title;
  const token = sessionStorage.getItem("token");
     //只有登录后才能访问其他页面
  if (to.path !== '/login') {
    if (!token) return next("/login");
    next();
  } else { 
    next();
  }
})

全局后置守卫

    router.afterEach((to, from) => {
})

1.路由守卫

【路由独享的】是指在单个路由配置的时候也可以设置的钩子函数.
运行在路由上的守卫 (相比上面的全局守卫 全局守卫:只要有跳转就会执行守卫函数 而路由守卫呢 是只有跳转到当前的路由时才执行路由守卫函数) 用处:一般做跳转判断

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      //路由守卫写在当前的路由上
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})

在/login上增加路由守卫实现从某个页面跳转过来登录成功后再跳转到某个页面:

{
    path: '/login',
    name: 'Login',
    component: () => import("../components/login.vue"),
    meta: {
      title:'Login'
    },
    //路由守卫
    beforeEnter: (to, from, next) => {
      to.query.enterUrl = from.path;
      next()
    }
  }
//login.vue组件
<script setup>
import {ref,reactive} from "vue"
import axios from  "axios"
import { useRoute,useRouter } from "vue-router";
const route=useRoute();
const router=useRouter()

const {params}=reactive({
  params:{
    username:'admin',
    password:'123'
  }
})
const dologin=()=>{
   axios.post("http://bufantec.com/api/test/user/doLogin")
   .then(res=>{
     console.log(res);
     const {data:message}=res;
     if(message.code!=="success") return;
     sessionStorage.setItem("token",message.sessionId);
     //获取保存的上一次跳转过来的路由
     var enterUrl=route.query.enterUrl;

     router.replace(enterUrl);
   })
}

</script>

2.组件内的守卫

【组件内的】:是指在组件内执行的钩子函数,类似于组件内的生命周期,相当于为配置路由的组件添加的生命周期钩子函数。
也可以理解为这个组件的生命周期 与全局守卫使用方法一致

onBeforeRouteEnter 不支持
onBeforeRouteUpdate(在组件复用的时候调用 用于解决组件复用问题)
onBeforeRouteLeave (导航离开该组件的对应路由时调用 这个离开守卫通常用来禁止用户在还未保存修改前突然离开。该导航可以通过 next(false) 来取消。 还可以用来清除定时器)

组件内的守卫与之前使用不同,vue-router4中,需要从vue-router内引入需要的插件。

<script setup>
import {onBeforeRouteLeave,onBeforeRouteUpdate } from "vue-router"
//组件内守卫
onBeforeRouteUpdate((to,from,next)=>{
  console.log("组件复用")
  next()
})
onBeforeRouteLeave((to,from,next)=>{
  const confirm= window.confirm("你确定要离开吗?");
  if(confirm){
    next();
  }else{
    next(false);
  }
})

</script>

3. 导航守卫回调参数

to:目标路由对象;

from:即将要离开的路由对象;

next:他是最重要的一个参数有以下注意点

1.但凡涉及到有next参数的钩子,必须调用next() 才能继续往下执行下一个钩子,否则路由跳转等会停止。

2.如果要中断当前的导航要调用next(false)。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到from路由对应的地址。(主要用于登录验证不通过的处理)

3.当然next可以这样使用,next(‘/‘) 或者 next({ path: ‘/‘ }): 跳转到一个不同的地址。意思是当前的导航被中断,然后进行一个新的导航。可传递的参数与router.push中选项一致。

4.在beforeRouteEnter钩子中next((vm)=>{})内接收的回调函数参数为当前组件的实例vm,这个回调函数在生命周期mounted之后调用,也就是,他是所有导航守卫和生命周期函数最后执行的那个钩子。

5.next(error): (v2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。

文档更新时间: 2023-01-02 15:41   作者:董老师