多角色管理

  • [ 思路 ]
    • 游客,会员,管理员,不同身份对应的页面数量是不同的,所以再token中要对角色身份和权限进行标记
    • 服务端需要对前端页面进行权限统筹,针对不同权限的用户,返回相应权限范围的页面和导航数据。
    • 前端收到与用户权限相对应的页面和导航数据后,进行匹配渲染。
    • 在导航守卫中加入资源预请求,根据请求到的页面和信息,动态的添加路由上去。
    router.beforeEach(async (to, form) => {
      // 防抖,当添加了动态路由以后,就不会再重复添加
      const state = router.getRoutes().find(r => r.name === 'home').children.length
      if(state) return
    
      // 白名单,登陆和注册页不进行动态路由添加
      if(to.path === '/login' || to.path === '/register') {
        return true
      } else {
    
        // 在该方法里面进行资源内容的缓存和提取,
        // 在缓存对象里面存放一个包含 token 和 data 属性的对象,
        // 检测该对象的 token 和 登陆后存储的 token 是否一致,
        // 一致就返回该对象的 data,否则从服务端获取 data,并将 token 和 data 同时写入该对象缓存起来。
        // 每次登陆后,token都会改变,资源将重新获取,否则从缓存获取。
        // 如果令牌过期,会跳转到登录页。资源同样将被重新缓存
        const {status, msg, data} = await getResource()
        if(status === 2) {
          // 处理路由配置
          const homeRoute = routes.find(r => r.name === 'home')
          homeRoute.children = []
          data.forEach((d, i) => {
            homeRoute.children.push({
              path: d.path,
              name: d.name,
              components: {
                home: comp[d.name]
              }
            })
            if(i==0) {
              homeRoute.children.push({
                path: '',
                name: d.name,
                components: {
                  home: comp[d.name]
                }
              })
            }
          })
    
          // 添加动态路由
          router.addRoute(homeRoute)
    
          // 重点,页面刷新会导致动态路由会消失,页面找不到路由出现白屏。
          // 刷新的时候,to.redirectedFrom 属性为空字符串,由此判断是刷新或者从其他站点直接跳转过来
          // 非空的话,说明是站内跳转过来的,正常情况下一定是已经加载了动态路由的。不会出现白屏问题
          if(to.redirectedFrom) {
    
            // 这里判断访问路径是否是站内注册了路由的页面路径
            // 如果能获得 name 属性,说明是合法路径,放行即可
            if(to.name) {
              return true
            }
    
            // 否则是非法路径,重定向去站点首页即可
            return {path: '/'}
          } else {
    
            // to.redirectedFrom 属性为空字符串,页面白屏,那么就重复一次路由跳转。
            // 当重复跳转到达页面的时候,动态路由已经被再次添加,页面正常显示。
            // 注意前面的两轮判断非常重要,如果没有的话,页面会进入重复跳转的死循环。
            return {...to, replace: true}
          }
        }else {
          // 获取资源失败,说明令牌认证有问题,跳转到登陆页面去登陆
          return {name: 'login'}
        }
      }
    })
    

  • [ 性能优化 ]
    • 上述操作有一个问题,就是每次路由跳转都会去重复预请求页面数据,造成资源浪费
    • 通过缓存处理进行性能优化
    • 参考
    // http/index.js
    // 这里我目前不会 pinia,所以用 localStorage 进行了缓存
    export const getResource = async function() {
       const resource = window.localStorage.getItem('resource')
       if(resource) {
          const source = JSON.parse(resource)
          if(source.token === window.localStorage.getItem('token')) {
             return source.data
          }
       }
       const data = await $.get('/resource')
    
       // 这里我从服务端返回的 状态码 一律是200,而在返回数据对象内部自己重新定义了 status 属性12345,所以是 2
       if(data.status !== 2) return []
       const source = {
          token: window.localStorage.getItem('token'),
          data 
       }
       window.localStorage.setItem('resource', JSON.stringify(source))
       return res(data)
    }
    
    posted @ 2024-04-08 09:34  anch  阅读(2)  评论(0编辑  收藏  举报