在vue3开发中,路由守卫是一个很重要的环节,vue router 是官方打造的一个路由管理器,它让我们能够方便的管理路由。在开发过程中,我们常常要考虑权限控制,这个时候就需要依赖路由守卫来控制了。
首先,我们需要知道路由守卫是什么?
官方文档是这样说的:
守卫分类
Vue 官方给路由守卫分成了五类,每种都有其独特的功能。
- 全局前置守卫
- 全局解析守卫
- 全局后置钩子
- 路由独享的守卫
- 组件内的守卫
下面我将分别介绍这些导航守卫的使用方法。
全局前置守卫
我们在刚开始使用掘金的时候,不需要登录也可以看里面的文章,但是当你想要给某篇文章点赞的时候它就会给你跳出登录页面,这就是你没有权限访问这个功能,前置路由守卫就是来干这种事情的,如果你需要访问没有权限的页面或交互功能,它会强制跳出登录页。
全局前置守卫注册方法如下:
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 中导航守卫的分类和使用方法。通过掌握这些知识,我们可以更好地进行路由权限控制、数据获取等操作,提高项目的开发效率。好了,有关于路由守卫的知识我就分享到这里了,希望对你有所帮助。