vue后台管理系統的菜單權限處理


1.

在首次請求登錄接口的時候,由后端返回相應的角色權限,再根據這個進行動態路由生成。

自己根據角色創建不同的路由表,然后在登錄時拿 到不同的角色標記,來引入對應的路由表。

 

2.把路由表存儲在vuex中,右側菜單通過直接引入vuex存的路由表進行渲染。

通過接口返回的角色權限,根據角色來動態的通過router.addRoutes(),添加不同的路由。

 

 

3.在路由守衛router.beforeEach中進行判斷

const hasRoles = store.getters.roles && store.getters.roles.length > 0
      if (hasRoles) {
        next()
      } else {
        try {
          // get user info
          // note: roles must be a object array! such as: ['admin'] or ,['developer','editor']
          const { roles } = await store.dispatch('user/getInfo')

          // generate accessible routes map based on roles
          const accessRoutes = await store.dispatch('permission/generateRoutes', roles)

          // dynamically add accessible routes
          router.addRoutes(accessRoutes)

          // hack method to ensure that addRoutes is complete
          // set the replace: true, so the navigation will not leave a history record
          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()
        }
      }

 

正以為如此很多人在使用動態添加路由addRoutes()會遇到下面的情況:
在addRoutes()之后第一次訪問被添加的路由會白屏,這是因為剛剛addRoutes()就立刻訪問被添加的路由,然而此時addRoutes()沒有執行結束,因而找不到剛剛被添加的路由導致白屏。因此需要從新訪問一次路由才行。

該如何解決這個問題 ?
此時就要使用next({ ...to, replace: true })來確保addRoutes()時動態添加的路由已經被完全加載上去。

next({ ...to, replace: true })中的replace: true只是一個設置信息,告訴VUE本次操作后,不能通過瀏覽器后退按鈕,返回前一個路由。

因此next({ ...to, replace: true })可以寫成next({ ...to }),不過你應該不希望用戶在addRoutes()還沒有完成的時候,可以點擊瀏覽器回退按鈕搞事情吧。

其實next({ ...to })的執行很簡單,它會判斷:

如果參數to不能找到對應的路由的話,就再執行一次beforeEach((to, from, next)直到其中的next({ ...to})能找到對應的路由為止。

也就是說此時addRoutes()已經完成啦,找到對應的路由之后,接下來將執行前往對應路由的beforeEach((to, from, next) ,因此需要用代碼來判斷這一次是否就是前往對應路由的beforeEach((to, from, next),如果是,就執行next()放行。

如果守衛中沒有正確的放行出口的話,會一直next({ ...to})進入死循環 !!!

因此你還需要確保在當addRoutes()已經完成時,所執行到的這一次beforeEach((to, from, next)中有一個正確的next()方向出口。

因此想實現動態添加路由的操作的話,代碼應該是這樣的:

router.beforeEach((to, from, next) => {
const token = sessionStorage.getItem('access_token')
// 存在 token 說明已經登錄
if (token) {
// 登錄過就不能訪問登錄界面,需要中斷這一次路由守衛,執行下一次路由守衛,並且下一次守衛的to是主頁'
if (to.path === '/login') {
next({ path: '/' })
}
// 保存在store中路由不為空則放行 (如果執行了刷新操作,則 store 里的路由為空,此時需要重新添加路由)
if (store.getters.getRoutes.length || to.name != null) {
//放行
next()
} else {
// 將路由添加到 store 中,用來標記已添加動態路由
store.commit('ADD_ROUTER', '需要添加的路由')
router.addRoutes('需要添加的路由')
// 如果 addRoutes 並未完成,路由守衛會一層一層的執行執行,直到 addRoutes 完成,找到對應的路由
next({ ...to, replace: true })
}
} else {
// 未登錄時,注意 :在這里也許你的項目不只有 logon 不需要登錄 ,register 等其他不需要登錄的頁面也需要處理
if (to.path !== '/logon') {
next({ path: '/logon' })
} else {
next()
}
}

 

4.在路由文件中實例化了路由,會導致在vuex中獲取不到路由列表,打印undefined。最后通過(路由懶加載)路由文件中的component引入方式改為

component: () => import('@/views/clipboard/index'),解決。  (不知道什么原因獲取不到??)


5.   退出或切換角色時需要路由重置,防止因為router.addroutes()導致路由重復添加

router/index.js  文件

const createRouter = () => new Router({ // mode: 'history', // require service support scrollBehavior: () => ({ y: 0 }), routes: constantRoutes }) const router = createRouter() // Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
// 退出或切換角色時需要路由重置,防止因為router.addroutes()導致路由重復添加
export function resetRouter() { //重置方法 const newRouter = createRouter() router.matcher = newRouter.matcher // reset router }

 

 6.vuex中批量引入所有的modules文件

//webpack批量引入文件

const modulesFiles = require.context('./modules', true, /\.js$/) // you do not need `import app from './modules/app'` // it will auto require all vuex module from modules file const modules = modulesFiles.keys().reduce((modules, modulePath) => { // set './app.js' => 'app' const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1') const value = modulesFiles(modulePath) modules[moduleName] = value.default return modules }, {}) const store = new Vuex.Store({ modules, getters })

 

 7. vuex namespaced的作用以及使用方式

vuex中的store分模塊管理,需要在store的index.js中引入各個模塊,為了解決不同模塊命名沖突的問題,將不同模塊的namespaced:true,之后在不同頁面中引入getter、actions、mutations時,需要加上所屬的模塊名

 

const state = {
  token: getToken(),
  name: '',
  avatar: '',
  introduction: '',
  roles: []
}

const mutations = {
  SET_TOKEN: (state, token) => {
    state.token = token
  },
}

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)
      })
    })
  },
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}

 

 8.router.addRoutes添加的動態路由,刷新頁面后跳到404頁面

在使用addRoutes之前我就定義了,通配符 * 跳轉到404頁面如下圖: 這就是問題所在。
解決方法是 不要再路由中添加404頁面 在addRoutes里進行拼接 (通配符 * 跳轉到404頁面的路由)

在beforeEach中打印 to發現是404 打印from顯示是/

當頁面一刷新 addRoutes 還沒有添加上 路由就開始跳轉了 所以找不到路由就跳轉到404頁面了

 

 

 

 轉:https://blog.csdn.net/qq_37121488/article/details/88287066

轉:https://blog.csdn.net/qq_41912398/article/details/109231418

轉:https://blog.csdn.net/fuck487/article/details/83411856?utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM