Vue 3 的5种路由守卫

在vue3开发中,路由守卫是一个很重要的环节,vue router 是官方打造的一个路由管理器,它让我们能够方便的管理路由。在开发过程中,我们常常要考虑权限控制,这个时候就需要依赖路由守卫来控制了。

首先,我们需要知道路由守卫是什么?

官方文档是这样说的:

守卫分类

Vue 官方给路由守卫分成了五类,每种都有其独特的功能。

  1. 全局前置守卫
  2. 全局解析守卫
  3. 全局后置钩子
  4. 路由独享的守卫
  5. 组件内的守卫

下面我将分别介绍这些导航守卫的使用方法。

全局前置守卫

我们在刚开始使用掘金的时候,不需要登录也可以看里面的文章,但是当你想要给某篇文章点赞的时候它就会给你跳出登录页面,这就是你没有权限访问这个功能,前置路由守卫就是来干这种事情的,如果你需要访问没有权限的页面或交互功能,它会强制跳出登录页。

全局前置守卫注册方法如下:

javascript 复制代码
router.beforeEach((to, from) => {
  // ...
  // 返回 false 取消导航
  return false
})

当一个导航触发时,全局前置守卫会按照创建顺序调用。守卫是异步解析执行,导航在所有守卫 resolve 完之前一直处于等待中。 示例:

javascript 复制代码
router.beforeEach(async (to, from) => {
  if (
    // 检查用户是否已登录
    !isAuthenticated &&
    // 避免无限重定向
    to.name !== 'Login'
  ) {
    // 将用户重定向到登录页面
    return { name: 'Login' }
  }
})

其实它还有第三个参数next,但是官方认为这是一个常见的错误来源,所以在某次更新的时候将它移除了,但是当前版本仍然支持这种写法: 比如我最近的项目中:

js 复制代码
// 全局路由守卫
const whitePass = ['/login', '/register','/noteClass']
router.beforeEach((to, from, next) => {
  document.title = to.meta.title
  if (!whitePass.includes(to.path)) { // 需要校验
    // 判断浏览器本地有无userInfo
    if (!localStorage.getItem('userInfo')) { //没登录
      next('/login')
      return
    }
    next()
    return
  }
  next()
})

全局解析守卫

我们常常会在数据预加载 或者需要依赖检查的时候使用全局解析守卫。例如,在路由确认前,可以在这里进行数据的异步加载,确保组件渲染时已有所需数据,或者某些页面需要特定的浏览器插件或硬件支持(如摄像头),可以在全局解析守卫中进行检查,并在不符合条件时取消导航。

全局解析守卫注册方法如下:

javascript 复制代码
router.beforeResolve(async to => {
  // ...
})

全局解析守卫在导航被确认之前、所有组件内守卫和异步路由组件被解析之后调用。

例如:在访问某些需要访问令牌(Access Token)的页面之前,我们可以在全局解析守卫中进行令牌的验证,确保用户具有合法的访问权限。

javascript 复制代码
router.beforeResolve(async to => {
  if (to.meta.requiresToken) {
    try {
      const isValidToken = await verifyAccessToken()
      if (!isValidToken) {
        // 如果令牌无效,重定向到登录页面
        return { name: 'Login' }
      }
    } catch (error) {
      // 如果验证过程中出现错误,可以记录错误并重定向到错误页面
      return { name: 'Error', params: { error: error.message } }
    }
  }
})

全局后置钩子

全局后置钩子注册方法如下:

javascript 复制代码
router.afterEach((to, from) => {
  // ...
})

全局后置钩子不会接受 next 函数,也不会改变导航本身。它们对于分析、更改页面标题等辅助功能很有用。

在单页应用中,用户可能需要在多个页面间切换工作。使用全局后置钩子,我们可以在用户每次切换路由时自动保存他们的浏览状态,以便于下次访问时恢复。 如:保存用户浏览历史

javascript 复制代码
router.afterEach((to, from) => {
  // 假设有一个函数 saveUserHistory 用于保存用户的浏览历史
  saveUserHistory({
    fullPath: to.fullPath,
    time: new Date()
  });
});

每当用户导航到一个新的路由,saveUserHistory 函数就会被调用来记录用户访问的页面路径和时间。这样,应用可以在用户下次启动时恢复他们的浏览位置,提供更加个性化的用户体验。 请注意,这里的 saveUserHistory 函数是一个假设的函数,实际应用中你需要根据你的数据存储方式(如本地存储、IndexedDB、服务器等)来实现相应的逻辑。

路由独享的守卫

在具有用户角色的应用中,某些页面可能只对特定角色开放。使用路由独享的守卫,可以在用户尝试访问这些页面时验证他们的角色。 如:限制访问管理员页面

javascript 复制代码
const routes = [
  {
    path: '/admin/settings',
    component: AdminSettings,
    beforeEnter: (to, from) => {
      // 假设有一个函数 checkUserRole 来检查用户角色
      if (!checkUserRole('admin')) {
        // 如果用户不是管理员,取消导航并重定向到登录页面
        return { name: 'Login' }
      }
    },
  },
]

在这个示例中,beforeEnter 守卫检查用户是否拥有管理员权限,如果没有,则导航会被取消,并且用户会被重定向到登录页面。这确保了只有具有管理员权限的用户才能访问管理员设置页面。 请注意,这里的 checkUserRole 函数是一个假设的函数,你需要根据你的用户认证逻辑来实现它。这通常涉及到检查用户的角色信息,这些信息可能存储在本地状态、会话或认证令牌中。

组件内的守卫

我们常常会在组件级别数据获取、处理动态路由参数变化、未保存更改的警告等方面去使用组件内的守卫

  • 组件级别的数据获取 在 Vue 组件中,经常需要在渲染前获取数据。使用 beforeRouteEnter 守卫可以在组件被创建前进行数据获取,并将数据传递给组件实例。 如:在用户详情组件中获取用户数据
javascript 复制代码
export default {
  beforeRouteEnter(to, from, next) {
    // 假设有一个函数 fetchUserData 用于从服务器获取用户数据
    fetchUserData(to.params.id).then(data => {
      next(vm => {
        // 通过 vm 设置组件的数据属性
        vm.userData = data;
      });
    });
  },
  data() {
    return {
      userData: null
    };
  }
}

beforeRouteEnter 守卫在组件实例化之前被调用,它使用 fetchUserData 函数异步获取用户数据,并通过 next 函数的回调将数据赋值给组件的 userData 数据属性。

  • 处理动态路由参数变化 当路由参数变化时,组件实例会被复用,此时可以使用 beforeRouteUpdate 守卫来处理参数变化带来的影响。 如:更新用户详情组件的数据
javascript 复制代码
export default {
  beforeRouteUpdate(to, from, next) {
    // 假设有一个函数 fetchUserData 用于从服务器获取用户数据
    fetchUserData(to.params.id).then(data => {
      // 更新组件的数据属性
      this.userData = data;
      next();
    });
  },
  data() {
    return {
      userData: null
    };
  }
}

每当用户详情页面的路由参数(如用户 ID)发生变化时,beforeRouteUpdate 守卫会被触发,它会重新获取用户数据并更新组件的 userData

  • 未保存更改的警告 在用户尝试离开当前页面时,如果存在未保存的更改,可以使用 beforeRouteLeave 守卫来提示用户确认是否离开。 如:提示用户保存更改
javascript 复制代码
export default {
  beforeRouteLeave(to, from, next) {
    if (this.hasUnsavedChanges) {
      const answer = window.confirm('Do you really want to leave? you have unsaved changes!');
      if (!answer) return false;
    }
    next();
  },
  data() {
    return {
      hasUnsavedChanges: false
    };
  }
}

如果组件的 hasUnsavedChanges 属性为 true,则 beforeRouteLeave 守卫会弹出一个确认对话框,询问用户是否真的想要离开当前页面。如果用户选择取消,则导航会被取消。

总结

本文详细介绍了 Vue Router 中导航守卫的分类和使用方法。通过掌握这些知识,我们可以更好地进行路由权限控制、数据获取等操作,提高项目的开发效率。好了,有关于路由守卫的知识我就分享到这里了,希望对你有所帮助。

相关推荐
(⊙o⊙)~哦1 小时前
JavaScript substring() 方法
前端
无心使然云中漫步2 小时前
GIS OGC之WMTS地图服务,通过Capabilities XML描述文档,获取matrixIds,origin,计算resolutions
前端·javascript
Bug缔造者2 小时前
Element-ui el-table 全局表格排序
前端·javascript·vue.js
xnian_3 小时前
解决ruoyi-vue-pro-master框架引入报错,启动报错问题
前端·javascript·vue.js
罗政3 小时前
[附源码]超简洁个人博客网站搭建+SpringBoot+Vue前后端分离
vue.js·spring boot·后端
麒麟而非淇淋3 小时前
AJAX 入门 day1
前端·javascript·ajax
2401_858120533 小时前
深入理解MATLAB中的事件处理机制
前端·javascript·matlab
阿树梢4 小时前
【Vue】VueRouter路由
前端·javascript·vue.js
随笔写5 小时前
vue使用关于speak-tss插件的详细介绍
前端·javascript·vue.js
史努比.5 小时前
redis群集三种模式:主从复制、哨兵、集群
前端·bootstrap·html