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

相关推荐
Boilermaker199242 分钟前
【Java EE】SpringIoC
前端·数据库·spring
中微子1 小时前
JavaScript 防抖与节流:从原理到实践的完整指南
前端·javascript
天天向上10241 小时前
Vue 配置打包后可编辑的变量
前端·javascript·vue.js
芬兰y1 小时前
VUE 带有搜索功能的穿梭框(简单demo)
前端·javascript·vue.js
好果不榨汁2 小时前
qiankun 路由选择不同模式如何书写不同的配置
前端·vue.js
小蜜蜂dry2 小时前
Fetch 笔记
前端·javascript
拾光拾趣录2 小时前
列表分页中的快速翻页竞态问题
前端·javascript
小old弟2 小时前
vue3,你看setup设计详解,也是个人才
前端
Lefan2 小时前
一文了解什么是Dart
前端·flutter·dart
Patrick_Wilson2 小时前
青苔漫染待客迟
前端·设计模式·架构