- 实现思路
- 动态权限数据存储:在服务端维护用户权限数据,用户登录或权限变更时,将最新权限数据返回给前端。前端可以将权限数据存储在Vuex中,方便全局访问。
- 路由元信息定义:在
router/index.js
文件中定义路由时,在meta
字段里设置权限相关信息,例如meta: { requiresAuth: true, roles: ['admin', 'editor'] }
,表示该路由需要认证且特定角色可访问。
- 运行时更新路由元信息
- 监听权限变更:在Vuex的
mutation
中,当接收到服务端返回的新权限数据时,触发更新操作。
- 遍历路由更新:通过
router.options.routes
获取所有路由,遍历每个路由,根据新的权限数据更新其meta
字段。例如:
import router from '@/router'
export const updateRouteMeta = (newPermissions) => {
router.options.routes.forEach(route => {
// 根据新权限数据逻辑更新route.meta
if (newPermissions.includes(route.meta.requiredPermission)) {
route.meta.allowAccess = true
} else {
route.meta.allowAccess = false
}
})
router.addRoutes(router.options.routes)
}
- 确保已打开页面权限同步更新
- 导航守卫:在全局前置守卫
router.beforeEach
中,每次路由切换时检查当前用户权限与目标路由的元信息是否匹配。
router.beforeEach((to, from, next) => {
const userPermissions = store.getters.getUserPermissions
if (to.meta.requiresAuth &&!userPermissions.includes(to.meta.requiredPermission)) {
next({ name: 'Login' })
} else {
next()
}
})
- **组件内守卫**:对于已经打开的页面,在组件的`beforeRouteUpdate`守卫中再次检查权限,确保权限变更后页面能正确处理。
export default {
beforeRouteUpdate(to, from, next) {
const userPermissions = this.$store.getters.getUserPermissions
if (to.meta.requiresAuth &&!userPermissions.includes(to.meta.requiredPermission)) {
this.$router.push({ name: 'Login' })
} else {
next()
}
}
}
- 性能优化
- 缓存路由元信息:在Vuex中缓存已处理的路由元信息,每次权限变更时,先对比新老权限数据和缓存的路由元信息,只有真正发生变化时才更新路由元信息和重新遍历路由。
- 节流与防抖:对于权限变更频繁的场景,使用节流(throttle)或防抖(debounce)技术,避免短时间内多次重复的权限判断和路由更新操作。例如,使用Lodash的
debounce
:
import { debounce } from 'lodash'
const updateRouteMetaDebounced = debounce(updateRouteMeta, 300)
// 当权限变更时调用updateRouteMetaDebounced
- **按需加载组件**:配置路由时使用动态导入组件(`const Home = () => import('@/views/Home.vue')`),只有在需要访问该路由时才加载组件,减少初始加载时间。同时,当权限变更导致组件不可见时,利用Vue的`keep - alive`结合`include`、`exclude`属性控制组件的缓存与销毁,避免不必要的重渲染。