<em id="09ttv"></em>
    <sup id="09ttv"><pre id="09ttv"></pre></sup>
    <dd id="09ttv"></dd>

        • 根據(jù)用戶權(quán)限不同,動態(tài)生成路由導(dǎo)航菜單(一)

          2019-12-27    seo達人

          首先讓我們了解一下前端路由:路由router全部配置在前端,根據(jù)用戶權(quán)限判斷可以進入哪些頁面

          缺點:



          vue初始化的時候需要掛載全部路由,對性能有影響

          安全性低,用戶可以在地址欄跳轉(zhuǎn)到無權(quán)訪問的頁面(可優(yōu)化)

          動態(tài)路由則是根據(jù)用戶信息獲取權(quán)限,簡單來說就是根據(jù)用戶信息獲取其對應(yīng)的權(quán)限,生成對應(yīng)的路由掛載,然后動態(tài)渲染有權(quán)限的菜單于側(cè)邊欄



          實現(xiàn)

          定義靜態(tài)路由(登錄或者公用頁面)、動態(tài)路由,vue初始化時只掛載靜態(tài)路由

          用戶登錄后,拿到用戶token,調(diào)接口拿到動態(tài)路由權(quán)限D(zhuǎn)ynamicRoutes,將DynamicRoutes和定義的動態(tài)路由比較,篩選出相應(yīng)的用戶可訪問路由表

          執(zhí)行router.addRoutes(DynamicRoutes)添加動態(tài)路由

          使用vuex存儲路由表,根據(jù)vuex中可訪問的路由渲染側(cè)邊欄sidebar

          // beforeEach中

          if (getToken() && getToken() !== 'undefined') {

            // 權(quán)限判斷

            if (!store.state.app.menuPermissions) {

              / 獲取后臺給的權(quán)限數(shù)組 /

              return new Promise((resolve, reject) => {

                getPermissionList().then(response => {

                  if (response.data.stat === 1) {

                    const userRouter = response.data.data

                    // 檢查并生成新的路由表

                    const DynamicRoutes = ChecAndSetPermissionRouter(userRouter)

                    // 默認使/重定向到第一個有效的路由

                    for (let i = 0, leni = DynamicRoutes.length; i < leni; i++) {

                      if (DynamicRoutes[i].children.length > 0) {

                        DynamicRoutes[i].path = '/'

                        DynamicRoutes[i].redirect = DynamicRoutes[i].children[0].path

                        break

                      }

                    }

                    DynamicRoutes.push({ path: '', redirect: '/404', hidden: true }) // 全局404

                    /
          生成左側(cè)導(dǎo)航菜單 /

                    store.dispatch('SetMenuPermissions', DynamicRoutes)



                    /
            動態(tài)添加路由 /

                    router.addRoutes(DynamicRoutes)



                    // /
          完整的路由表 /

                    store.dispatch('SetRouterPemissions', [...constantRouterMap, ...DynamicRoutes])

                    next(to)

                  }

                }).catch(error => {

                  router.push('/404')

                  // /
          生成左側(cè)導(dǎo)航菜單 */

                  store.dispatch('SetMenuPermissions', [])

                  next()

                  reject(error)

                })

              })

            }

            if (to.path === '/login') {

              next({ path: '/' })

            } else {

              next()

            }

          } else {

            if (whiteList.indexOf(to.path) !== -1) {

              next()

            } else {

              next(/login?redirect=${to.path}) // 否則全部重定向到登錄頁

            }

          }



          踩坑來了





          Q:為什么404 頁面一定要最后加載,放置在靜態(tài)路由中會怎么樣?

          放在靜態(tài)路由里,后面的所以頁面都會被攔截到404,所以應(yīng)該獲取動態(tài)路由權(quán)限之后push

          Q:權(quán)限獲取成功,不跳轉(zhuǎn)新生成的動態(tài)路由,跳404?

          beforeEach中router.addRoutes之后的next()可能會失效,因為可能next()的時候路由并沒有完全add完成,可替換成next(to),重新進入router.beforeEach這個鉤子,這時候再通過next()來釋放鉤子,就能確保所有的路由都已經(jīng)掛在完成了。

          Q:$router.addRoutes()動態(tài)添加的路由怎么刪除掉?

          在開發(fā)中,有新增編輯刪除菜單并要求左側(cè)邊欄菜單及時更新的需求,如果直接addRoutes,warn如下:



          解決:addRoutes之前要清除掉上次addRoutes的路由,所以操作菜單調(diào)取權(quán)限后重新初始化router,進行matcher賦值



          // DynamicRoutes是權(quán)限路由

          const createRouter = () => new Router({

            mode: 'hash',

            routes: []

          })

          const newRouter = createRouter()

          // resetRouter()

          this.$router.matcher = newRouter.matcher

          this.$router.addRoutes(DynamicRoutes)



          Q:莫名其妙的無限循環(huán)

          vue-admin-template,遇到二級菜單children為空的權(quán)限,報錯如下:

          解決:按照github-issues上方法,在SidebarItem.vue里改一下data就好了(沒想通為啥)



          // 更改后如下,return {}

          data() {

              this.onlyOneChild = null

              return {}

          }



          附:ChecAndSetPermissionRouter



          import { dynamicRouterMap } from '@/router'



          export function ChecAndSetPermissionRouter(permissionDatas) {

            // 獲取到權(quán)限hashmap

            var permissionHashMap = null

            permissionHashMap = GetPermissionHashMap(permissionDatas)

            // 標記路由表

            var newDynamicRouterMap = []

            newDynamicRouterMap = objDeepCopy(dynamicRouterMap)

            newDynamicRouterMap.forEach(item => {

              MarkRouter(null, item, permissionHashMap)

            })

            // 重設(shè)路由表

            for (let i = 0; i < newDynamicRouterMap.length; i++) {

              if (ResetRouter(newDynamicRouterMap, newDynamicRouterMap[i])) {

                i-- // 注意:防止移除后索引錯位

              }

            }

            return newDynamicRouterMap

          }

          function GetPermissionHashMap(permissionDatas) {

            var permissionHashMap = {}

            permissionDatas.forEach(item => {

              SetKeyValueOfNodes(null, item, permissionHashMap)

            })

            return Object.assign({}, permissionHashMap)

          }



          // 深拷貝,遞歸重新設(shè)置前端路由表,避免數(shù)據(jù)復(fù)用

          function objDeepCopy(source) {

            var sourceCopy = source instanceof Array ? [] : {}

            for (var item in source) {

              sourceCopy[item] = typeof source[item] === 'object' ? objDeepCopy(source[item]) : source[item]

            }

            return sourceCopy

          }



          // 為權(quán)限hashmap的屬性賦值,新增屬性tempKey/tempKey2

          function SetKeyValueOfNodes(p, c, permissionHashMap) {

            // 需要匹配的組合類型

            var tempKey = (p ? p.name : 0) + '' + c.name

            var tempKey2 = c.name + '
          ' + c.name

            // 賦值

            permissionHashMap[tempKey] = 1

            permissionHashMap[tempKey2] = 1

            // 遞歸遍歷子節(jié)點賦值

            if (c.children != null && c.children.length > 0) {

              c.children.forEach(item => {

                SetKeyValueOfNodes(c, item, permissionHashMap)

              })

            }

          }



          // 標記路由表

          function MarkRouter(p, c, permissionHashMap) {

            var key = (p ? p.meta.title : 0) + '_' + c.meta.title

            // 使用拼接的key作為參考標記去匹配有權(quán)限的路由表

            if (HasPermission(key, permissionHashMap)) {

              if (p != null) {

                p.keep = true // 保留當前節(jié)點

              }

              if (c != null) {

                c.keep = true

              }

            }

            if (c.children && c.children.length > 0) {

              c.children.forEach(item => {

                MarkRouter(c, item, permissionHashMap)

              })

            }

          }



          // 校驗后端接口是否存在當前節(jié)點

          function HasPermission(key, permissionHashMap) {

            return permissionHashMap[key] === 1

          }



          // 重置路由表

          function ResetRouter(p, c) {

            if (c == null) {

              return false

            }

            if (p.children && !c.keep) {

              p.children.splice(p.children.indexOf(c), 1)

              return true

            } else if (!c.keep) {

              p.splice(p.indexOf(c), 1)

              return true

            }

            if (c.children && c.children.length > 0) {

              for (let i = 0; i < c.children.length; i++) {

                if (ResetRouter(c, c.children[i])) {

                  i-- // 注意:防止移除后索引錯位

                }

              }

            }

            return false

          }




          日歷

          鏈接

          個人資料

          藍藍設(shè)計的小編 http://m.sdgs6788.com

          存檔

          久久受www免费人成_看片中文| 亚洲AV日韩AV天堂久久| 久久久久久综合一区中文字幕 | 久久免费视频网站| 国产2021久久精品| 97香蕉久久夜色精品国产| 亚洲精品tv久久久久久久久 | 观看 国产综合久久久久鬼色 欧美 亚洲 一区二区 | 韩国免费A级毛片久久| 香港aa三级久久三级| 久久综合久久美利坚合众国| 色欲av伊人久久大香线蕉影院 | 久久久久亚洲AV无码麻豆| 999久久久国产精品| 人妻精品久久久久中文字幕69| 久久久久国产一区二区三区| 久久久久人妻一区二区三区vr| 久久久WWW成人免费毛片| av无码久久久久不卡免费网站| 久久午夜福利电影| 久久国产亚洲高清观看| 久久久久亚洲精品日久生情| 久久激情五月丁香伊人| 欧美一区二区精品久久| 久久99精品久久久久久hb无码 | 91精品国产91久久久久福利| 伊人久久大香线蕉综合影院首页| 久久本道伊人久久| 国产精品久久久久jk制服| 久久亚洲AV成人无码| 日韩影院久久| www亚洲欲色成人久久精品| 久久不见久久见免费视频7| 亚洲欧美日韩中文久久| 国产精品久久久久久五月尺| 久久免费美女视频| 国产亚洲婷婷香蕉久久精品| 综合久久精品色| 久久精品国产男包| 久久精品极品盛宴观看| 中文字幕亚洲综合久久菠萝蜜|