vue-admin-template角色权限设置(2)

vue-admin-template角色权限设置(2)

在vue-admin-template角色权限设置(1)中提到了如何根据用户角色进行访问控制
但在项目实际使用过程中发现了一些存在的问题,下面主要针对这些存在的问题进行修改和完善

1 页面刷新后发现头像等个人信息消失


  • 原因:在页面登录成功后,项目是通过getInfo方法获取个人信息存储在vuex中使用的,但是在页面刷新后,vuex中的数据会丢失。这是因为js代码是运行内存中的,代码运行时的所有变量、函数都是保存在内存中的。进行刷新页面的操作,以前申请的内存被释放,重新加载脚本代码,变量重新赋值,所以这些数据要想存储就必须存储在外部。
  • 解决方法:获取数据后在Storage中保存一份,这里采用localStorage
  • 需要注意的是:尽量不要在localStorage中存储过大的数据,否则会影响页面加载性能
import { login, logout, getInfo } from '@/api/user'import { getToken, setToken, removeToken } from '@/utils/auth'import { resetRouter } from '@/router'const getDefaultState = () => {  return {    // 利用localStorage保证刷新后仍存在    token: getToken(),    name: localStorage.getItem('name') ? JSON.parse(localStorage.getItem('name')) : '',    avatar: localStorage.getItem('avatar') ? JSON.parse(localStorage.getItem('avatar')) : '',    roles: localStorage.getItem('roles') ? JSON.parse(localStorage.getItem('roles')) : []  }}const state = getDefaultState()const mutations = {  RESET_STATE: (state) => {    Object.assign(state, getDefaultState())  },  SET_TOKEN: (state, token) => {    state.token = token  },  SET_NAME: (state, name) => {    state.name = name  },  SET_ROLES: (state, roles) => {    state.roles = roles  },  SET_AVATAR: (state, avatar) => {    state.avatar = avatar  }}const actions = {  // user login  login({ commit }, userInfo) {    const { username, password } = userInfo    return new Promise((resolve, reject) => {      login({ username: username.trim(), password: password }).then(response => {        const { data } = response        commit('SET_TOKEN', data.token)        setToken(data.token)        resolve()      }).catch(error => {        reject(error)      })    })  },  // get user info  getInfo({ commit, state }) {    return new Promise((resolve, reject) => {      getInfo(state.token).then(response => {        const { data } = response;        if (!data) {          return reject('验证失败,请重新登录!')        }        const { name, roles, avatar } = data        // 将个人信息备份在localStorage中        localStorage.setItem('roles', JSON.stringify(roles))        localStorage.setItem('roles', JSON.stringify(roles))        localStorage.setItem('avatar', JSON.stringify(avatar))        if (!roles || roles.length <= 0) {          reject('您不是有效的身份!')        }        // 将页面级的操作权限存在localStorage里        if (roles.includes('店长')) {          localStorage.setItem('permissions', JSON.stringify(['add', 'editAndDelete']));        } else if (roles.includes('收银员') || roles.includes('技师') || roles.includes('发型师')) {          localStorage.setItem('permissions', JSON.stringify([]));        }        commit('SET_NAME', name)        commit('SET_ROLES', roles)        commit('SET_AVATAR', avatar)        resolve(data)      }).catch(error => {        reject(error)      })    })  },  // user logout  logout({ commit, state }) {    return new Promise((resolve, reject) => {      logout(state.token).then(() => {        removeToken() // must remove  token  first        resetRouter()        // 记得清除        localStorage.removeItem('permissions')        localStorage.removeItem('name')        localStorage.removeItem('roles')        localStorage.removeItem('avatar')        commit('RESET_STATE')        resolve()      }).catch(error => {        reject(error)      })    })  },  // remove token  resetToken({ commit }) {    return new Promise(resolve => {      removeToken() // must remove  token  first      // 记得清除      localStorage.removeItem('permissions')      localStorage.removeItem('name')      localStorage.removeItem('roles')      localStorage.removeItem('avatar')      commit('RESET_STATE')      resolve()    })  }}export default {  namespaced: true,  state,  mutations,  actions}

这样在刷新之后vuex中的值仍存在~

2 页面刷新后动态路由失效跳转/404页面的问题


  • 原因:一方面是刷新后相应的vuex存在的值失效,另一方面是即使值仍有效,但是addRoutes动态添加路由还没完成,页面就从静态找了,导致一直跳转404。
  • 解决方法:可以把routes存在localStorage中,这里因为之前把roles持久了,可以直接在路由前置守卫中对刷新这种情况进行特殊处理,主要思想是当动态路由表添加进去路由以后,再将404路由也动态添加进去!
  • 需要注意的是:多次调用router.addRoutes方法,会重复添加路由并警告路由名字重复,可以重新封装一个方法。
  1. 在router/index.js中重新封装addRoutes方法
// 解决路由命名重复的问题router.$addRoutes = params => {  router.matcher = new Router({    routes: router.options.routes  // 关键代码  }).matcher;  router.addRoutes(params);};
  1. 删除router/index.js静态路由中的用*来找404
{ path: '*', redirect: '/404', hidden: true }
  1. 在src/permission.js中对刷新情况单独处理
router.beforeEach(async (to, from, next) => {  // start progress bar  NProgress.start()  // set page title  document.title = getPageTitle(to.meta.title)  // determine whether the user has logged in  const hasToken = getToken()  if (hasToken) {    if (to.path === '/login') {      // if is logged in, redirect to the home page      next({ path: '/' })      NProgress.done()    } else {      // 在addRoutes()之后第一次访问被添加的路由会白屏,这是因为刚刚addRoutes()就立刻访问被添加的路由      // 然而此时addRoutes()没有执行结束,因而找不到刚刚被添加的路由导致白屏。因此需要从新访问一次路由才行。      // 此时就要使用next({ …to, replace: true })来确保addRoutes()时动态添加的路由已经被完全加载上去。      // next({ …to, replace: true })中的replace: true只是一个设置信息,告诉VUE本次操作后,不能通过浏览器后退按钮,返回前一个路由。      // 通过getInfo判断用户是否获得了权限角色      const hasRoles = store.getters.roles && store.getters.roles.length > 0;      if (hasRoles) {        // 如果是刷新        if (store.state.permission.routes.length == 0) {          // 根据角色生成可访问的路由          const accessRoutess = await store.dispatch('permission/generateRoutes', store.getters.roles);          // 动态添加路由          router.$addRoutes(accessRoutess);          // 404页面重定向必须放在最后面!否则一刷新和输入地址 就出问题跳404页面!          // 因为addRoutes动态添加路由还没完成,页面就从静态找了。          // 解决:当动态路由表添加进去路由以后,再将404路由也动态添加进去!          router.options.routes.push({ path: '*', redirect: '/404', hidden: true })          console.log(router.options.routes)          next({ ...to, replace: true });        } else {          next()        }      } else {        try {          // get user info          // 注意:roles必须是数组形式,如['admin'] or ,['developer','editor']          const { roles } = await store.dispatch('user/getInfo')          // 根据角色生成可访问的路由          const accessRoutes = await store.dispatch('permission/generateRoutes', roles);          // 动态添加路由          router.$addRoutes(accessRoutes);          // 404页面重定向必须放在最后面!否则一刷新和输入地址 就出问题跳404页面!          // 因为addRoutes动态添加路由还没完成,页面就从静态找了。          // 解决:当动态路由表添加进去路由以后,再将404路由也动态添加进去!          router.options.routes.push({ path: '*', redirect: '/404', hidden: true })          // 确保addRoutes完成          // 设置替换为true 这样导航不会留下历史记录          next({ ...to, replace: true });        } catch (error) {          // remove token and go to login page to re-login          await store.dispatch('user/resetToken')          Message.error(error || 'Has Error')          next(`/login?redirect=${to.path}`)          NProgress.done()        }      }    }  } else {    /* has no token*/    if (whiteList.indexOf(to.path) !== -1) {      // in the free login whitelist, go directly      next()    } else {      // other pages that do not have permission to access are redirected to the login page.      next(`/login?redirect=${to.path}`)      NProgress.done()    }  }})

至此再刷新发现没有问题啦!!The end.

免责声明:本网信息来自于互联网,目的在于传递更多信息,并不代表本网赞同其观点。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,并请自行核实相关内容。本站不承担此类作品侵权行为的直接责任及连带责任。如若本网有任何内容侵犯您的权益,请及时联系我们,本站将会在24小时内处理完毕。
相关文章
返回顶部