浅析Vue导航守卫:路由控制与权限管理,前端安全卫士

一、什么是导航守卫

当涉及到Vue路由时,导航守卫是一项非常有用的功能。导航守卫允许你在路由导航过程中执行一些操作,例如验证用户权限、重定向或取消导航等,导航守卫主要分为三种:全局导航守卫、独享导航守卫、组件内导航守卫。

二、全局导航守卫

全局导航守卫有三种:beforeEach(全局前置守卫)、beforeResolve(全局解析守卫)、afterEach(全局后置守卫)。

1.全局前置守卫

我们可以使用router.beforeEach注册一个全局前置守卫,beforeEach在路由切换之前调用,可以用来进行权限验证、登录状态检查等操作。

用户如果没有登录,只能访问登录界面,不能访问其他页面。用户如果登录了,就可以访问其他页面,不能访问登录页面。

js 复制代码
router.beforeEach((to, from, next) => {
  let token = userStore.token;
  // 如果用户已登录
  if(token) {
    // 访问登录页则跳回首页
    if(to.path == "/login"){
      next({path: "/"});
    } else {
      // 如果访问其他页面则放行
      next();
    }
  } else { // 如果用户未登录
    if(to.path == "/login"){
      next();
    } else {
      // 如果访问其他页面则返回登录界面
      next({path: "/login"});
    }
  }
})

三个参数的含义:

  • to: 表示即将要进入的目标路由。它是一个包含路由信息的对象,包括path、params、query等参数信息。我们可以通过to.path获取目标路由的路径,通过to.params获取目标路由的参数,通过to.query获取目标路由的查询参数等。
  • from: 表示当前导航正要离开的路由。它也是一个包含路由信息的对象,我们可以通过from.path获取当前路由的路径,通过from.params获取当前路由的参数,通过from.query获取当前路由的查询参数等。
  • next: 可选的第三个参数,是一个函数(放行函数),用于控制导航的行为。

这里列举一些next的具体用法:

  1. next():调用next()表示继续导航,即允许用户访问目标路由。
  2. next(false):调用next(false)表示终止导航,即不允许用户访问目标路由。这通常用于进行权限验证或者登录状态检查,如果条件不满足,则终止导航。
  3. next('/path'):调用next('/path')表示重定向导航到指定的路径。这可以用于在导航守卫中进行重定向,例如在未登录时将用户重定向到登录页面。
  4. next({ path: '/path' }):调用next({ path: '/path' })表示重定向导航到指定的路径。与上一个用法相似,但使用了一个包含路径的对象作为参数。
  5. next(error):调用next(error)表示终止导航并传递一个错误对象。这可以用于在导航守卫中处理错误情况,例如在网络请求失败时中止导航并显示错误信息。
  6. next(callback):调用next(callback)表示异步导航,其中callback是一个回调函数。这可以用于在导航守卫中执行异步操作,例如在获取数据后再继续导航。

请注意,next方法只能在导航守卫函数中调用,并且每个导航守卫函数只能调用一次next方法,只能调用一次。

2.全局解析守卫

我们可以用router.beforeResolve注册一个全局守卫。beforeResolve在路由切换之前调用,但在beforeEach守卫之后调用。在该守卫中,可以在导航被确认之前执行异步操作或者获取组件数据,可以在所有组件内守卫和异步路由组件被解析之后调用。

js 复制代码
router.beforeResolve((to, from, next) => {
  // 在这里执行一些操作,例如加载数据
  fetchData().then(() => {
    next();
  });
});

Vue-router的官网写道:router.beforeResolve是获取数据或执行任何其他操作(如果用户无法进入页面时你希望避免执行的操作)的理想位置。

3.全局后置守卫

我们可以使用router.afterEach方法注册一个全局后置钩子,afterEach在路由切换之后调用,可以用来进行页面统计、错误处理等操作,通常用于页面渲染完成后的操作。该守卫没有next参数,因此不能中止导航。

js 复制代码
router.afterEach((to, from) => {
  // 在这里执行一些操作,例如记录页面浏览历史
  trackPageView(to.path);
});

比如说我们就可以利用前置守卫和后置守卫制作一个进度条,当然我们还需要引入第三方库及其样式,这样项目上方会出现进度条。

js 复制代码
import nprogress from "nprogress";
import "nprogress/nprogress.css";
import router from "./router";

router.beforeEach((to, from, next) => {
  nprogress.start();
  next();
})
router.afterEach((to, from) => {
  nprogress.done();
})

三、独享导航守卫

除了全局导航守卫外,我们还可以在路由配置中为特定的路由定义独享的守卫。路由独享守卫仅对特定的路由生效,可以用于处理特定路由的逻辑。beforeEnter守卫只在进入路由时触发,不会在params、query或hash改变时触发。

例如,从/users/2进入到/users/3或者从/users/2#info进入到/users/2#projects时,守卫不会触发,只有在从一个不同的路由导航时,才会被触发。

js 复制代码
const routes = [
  {
    path: '/home',
    component: Home,
    beforeEnter: (to, from, next) => {
      // 在进入路由之前执行一些操作
      if (isLoggedIn()) {
        // 用户已登录,允许访问路由
        next();
      } else {
        // 用户未登录,重定向到登录页面
        next('/login');
      }
    }
  },
  // 其他路由配置...
]

通过使用独享导航守卫,我们可以在路由级别上对访问权限进行一定的控制。

四、组件内导航守卫

除了全局导航守卫和路由独享守卫外,我们还可以在路由组件内直接定义路由导航守卫。这些守卫将在组件的生命周期钩子中被调用,用于在组件内部控制路由导航行为。

  • beforeRouteEnter:用于在路由进入组件之前执行操作,无法通过this访问组件实例,因为当守卫执行时,组件实例还没被创建。
  • beforeRouteUpdate:用于在组件复用时,路由参数发生变化时执行操作,可以通过this访问组件实例,因为组件已经挂载好了。
  • beforeRouteLeave:用于在路由离开组件之前执行操作,可以通过this访问组件实例。
js 复制代码
const UserDetails = {
  template: `...`,
  beforeRouteEnter(to, from) {
    // 在渲染该组件的对应路由被验证前调用
    // 不能获取组件实例 `this` ! 
    // 因为当守卫执行时,组件实例还没被创建!
  },
  beforeRouteUpdate(to, from) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 `/users/:id`,在 `/users/1` 和 `/users/2` 之间跳转的时候,
    // 由于会渲染同样的 `UserDetails` 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 因为在这种情况发生的时候,组件已经挂载好了,导航守卫可以访问组件实例 `this`
  },
  beforeRouteLeave(to, from) {
    // 在导航离开渲染该组件的对应路由时调用
    // 与 `beforeRouteUpdate` 一样,它可以访问组件实例 `this`
  },
}

在beforeRouteEnter守卫中,可以通过传递一个回调函数给next方法来访问组件实例。这个回调函数会在路由确认之后被调用,此时组件实例已经被创建。回调函数的参数就是组件实例,因此可以通过这个参数访问组件实例的方法和属性。

js 复制代码
export default {
  beforeRouteEnter(to, from, next) {
    next(vm => {
      // 在进入组件之后执行一些操作
      // 可以访问组件实例的this上下文
      vm.doSomething();
    });
  },
  beforeRouteUpdate(to, from, next) {
    // 在这里执行一些操作,例如重新加载数据
    fetchData().then(() => {
      next();
    });
  },
  beforeRouteLeave(to, from, next) {
    // 在这里执行一些操作,例如提示用户保存未保存的数据
    if (hasUnsavedChanges) {
      if (confirm('你有未保存的数据,确定要离开吗?')) {
        next();
      } else {
        next(false);
      }
    } else {
      next();
    }
  },
};

五、最后的话

Vue导航守卫是Vue Router提供的一种机制,用于在路由导航过程中执行一些操作。全局守卫可以在整个应用程序的路由导航过程中被调用,而路由独享守卫只对特定的路由生效。通过使用导航守卫,我们可以实现权限验证、数据预加载等功能,提升用户体验和应用程序的安全性。

能力一般,水平有限,本文可能存在纰漏或错误,如有问题欢迎指正,感谢你阅读这篇文章,如果你觉得写得还行的话,不要忘记点赞、评论、收藏哦!祝生活愉快!

相关推荐
桂月二二33 分钟前
探索前端开发中的 Web Vitals —— 提升用户体验的关键技术
前端·ux
CodeClimb2 小时前
【华为OD-E卷 - 第k个排列 100分(python、java、c++、js、c)】
java·javascript·c++·python·华为od
沈梦研2 小时前
【Vscode】Vscode不能执行vue脚本的原因及解决方法
ide·vue.js·vscode
hunter2062062 小时前
ubuntu向一个pc主机通过web发送数据,pc端通过工具直接查看收到的数据
linux·前端·ubuntu
qzhqbb2 小时前
web服务器 网站部署的架构
服务器·前端·架构
刻刻帝的海角2 小时前
CSS 颜色
前端·css
轻口味2 小时前
Vue.js 组件之间的通信模式
vue.js
浪浪山小白兔3 小时前
HTML5 新表单属性详解
前端·html·html5
lee5763 小时前
npm run dev 时直接打开Chrome浏览器
前端·chrome·npm
2401_897579653 小时前
AI赋能Flutter开发:ScriptEcho助你高效构建跨端应用
前端·人工智能·flutter