vue+addRouters動的ルーティングメニューの実装

42840 ワード

ダイナミックルーティングという機能は、実は簡単でも簡単で、難しいと言っても少し難しいです.上コードloginコンポーネント
//template style  
<script>
import router from '@/router'  //    
import Layout from '@/layout'  //      1
import Block from '@/layout/block'   //      2,               
const _import = require('@/router/import')  //module.exports = file => () => import(`@/${file}/index.vue`)       。                 

export default {
  data() {
   return {   //         
      roleId: '',
      menuList: [],
      menu: [],
      topMenus: [],
      leftMenus: [],
      firstUrl: ''
    }
  },
  created() {  //     404           ,               
    router.options.routes = [
      {
        path: '/view/manager/login',
        component: () => import('@/view/manager/login')
      },
      {
        path: '/view/manager/404',
        component: () => import('@/view/manager/404'),
        hidden: true
      }
    ]
  },
  methods: {
    async getRole() {  //             Id,   Id           
      try {
        const res = await auth.privilege({
          method: 'get',
          roleId: this.roleId
        })
        console.log('role', res)
        //               ,            
        if (res.status === 0) {
          const _res = res.result.menus
          const permissions = res.result.permissions
          const o = this.menuList
          this.firstUrl = _res[0].menuUrl
          for (var i = 0; i < _res.length; i++) {
            var index = _res[i]
            o[i] = {}
            o[i].path = index.menuUrl
            o[i].meta = {}
            o[i].meta.title = index.menuName
            o[i].meta.icon = index.menuIcon
            o[i].parentMenuId = index.parentMenuId
            o[i].menuId = index.menuId
            o[i].moduleId = index.moduleId
            if (index.menuLevel === 1) {
              o[i].component = 'Layout'
              o[i].redirect = ''
              o[i].children = []
            } else if (index.menuLevel === 2) {
              o[i].component = 'Block'
              o[i].redirect = ''
              o[i].children = []
            } else if (index.menuLevel === 3) {
              o[i].component = index.menuUrl
            } else if (index.menuLevel === 4) {
              o[i].component = index.menuUrl
              o[i].hidden = true
            }
            if (index.moduleId === 1010 && index.parentMenuId === 0) {
              o[i].hidden = true
            } else if (index.moduleId === 1013 && index.parentMenuId === 0) {
              o[i].hidden = true
            }
          }
          for (var j = 0; j < o.length; j++) {
            var pindex = o[j]
            for (var k = 0; k < o.length; k++) {
              var cindex = o[k]
              if (cindex.parentMenuId === pindex.menuId) {
                pindex.children.push(cindex)
                pindex.redirect = pindex.children[0].path
              }
            }
          }
          o.forEach(item => {
            if (item.parentMenuId === 0) {
              this.menu.push(item)
            }
            if (item.parentMenuId === 0 && item.moduleId === 1010) {
              this.topMenus.push(item)
            }
            if (item.parentMenuId === 0 && item.moduleId === 1013) {
              this.topMenus.push(item)
            }
          })
          //           ,            sessionStorage 
          sessionStorage.setItem('permissions', JSON.stringify(permissions))
          sessionStorage.setItem('routerMenus', JSON.stringify(this.menu))
          sessionStorage.setItem('routerTopMenus', JSON.stringify(this.topMenus))
          var routes = filterAsyncRouter(this.menu)
          routes.push({
            path: '*',
            redirect: '/view/manager/404',
            hidden: true
          })
          //       
          routes.forEach(item => {
            router.options.routes.push(item)
          })
          //           ,         
          router.addRoutes(routes)
          //        vuex 
          this.$store.dispatch('user/getPermissions', permissions)
          this.$store.dispatch('user/getMenus', routes)
          this.$store.dispatch('user/getTopMenus', this.topMenus)
          this.$router.push(this.firstUrl)
        } else {
          this.$message({
            message: res.msg,
            type: 'warning'
          })
        }
      } catch (err) {
        console.log(err)
        this.buttonLoading = false
        this.$message({
          message: err.data.msg ? err.data.msg : '    ',
          type: 'warning'
        })
      }
    }
  }
}
//                
function filterAsyncRouter(asyncRouterMap) {
  const accessedRouters = asyncRouterMap.filter(route => {
    if (route.component) {
      if (route.component === 'Layout') { // Layout      
        route.component = Layout
      } else if (route.component === 'Block') { // Block      
        route.component = Block
      } else {
        route.component = _import(route.path.substring(1, route.path.length))
      }
    }
    if (route.children && route.children.length) {
      route.children = filterAsyncRouter(route.children)
    }
    return true
  })
  return accessedRouters
}

</script>

ページのリフレッシュ後の空白を防ぐために、もう一つの操作があります:App.vue
//template style    
<script>
import Layout from '@/layout'
import Block from '@/layout/block'
import router from './router'
const _import = require('@/router/import')

export default {
//      sessionStorage    
  created() {
    const userInfo = JSON.parse(sessionStorage.getItem('userInfo'))
    const routerMenus = JSON.parse(sessionStorage.getItem('routerMenus'))
    const routerTopMenus = JSON.parse(sessionStorage.getItem('routerTopMenus'))
    const permissions = JSON.parse(sessionStorage.getItem('permissions'))
    if (routerMenus && this.$store.state.user.menus.length === 0) {
      this.$store.dispatch('user/getUserInfo', userInfo)
      this.$store.dispatch('user/getMenus', routerMenus)
      this.$store.dispatch('user/getTopMenus', routerTopMenus)
      this.$store.dispatch('user/getPermissions', permissions)
      var routes = filterAsyncRouter(routerMenus)
      routes.push({
        path: '*',
        redirect: '/view/manager/404',
        hidden: true
      })
      //        
      //       
      routes.forEach(item => {
        router.options.routes.push(item)
      })
      //           
      router.addRoutes(routes)
    }
  }

}

function filterAsyncRouter(asyncRouterMap) {
  const accessedRouters = asyncRouterMap.filter(route => {
    if (route.component) {
      if (route.component === 'Layout') {
        route.component = Layout
      } else if (route.component === 'Block') {
        route.component = Block
      } else {
        route.component = _import(route.path.substring(1, route.path.length))
      }
    }
    if (route.children && route.children.length) {
      route.children = filterAsyncRouter(route.children)
    }
    return true
  })
  return accessedRouters
}
</script>

これで大功を成し遂げた.ルーティングフォーマットを処理するブロックは業務と強い関連性があるが、論理は大きく異なる:1、バックエンドが直接処理したルーティングリストに戻ると、みんな喜んで、直接使えばいい.2,バックエンドがフロントエンドに戻るのが各ルーティング間の関係であれば,フロントエンド自身が必要なルーティングリストに変換する必要がある.しかしフロントエンドは,各層のルーティング間のつながりを明らかにすれば,処理は難しくない.3,フロントエンドで必ず知る各ルート関係データ
  • 各レベルのルーティングid
  • 各レベルのルーティングのname
  • 各レベルのルーティングpath
  • 各レベルルーティングが属するlevel
  • 各レベルルーティングicon
  • 各レベルのルーティングのidに対応する属する親のid