vue-admin-template中vue动态路由不显示问题解决

使用的的是vue-admin-template,这是一个极简的 vue admin 管理后台,它只包含了 Element UI & axios & iconfont & permission control & lint,这些搭建后台必要的东西。需要根据自己的需求二次开发。
线上地址:vue-admin-template
国内访问:vue-admin-template

  • 开发了一个公司内部的后台管理系统
  • 路由信息是登录成功后台返回,然后动态添加的
  • 遇到的问题:动态添加路由死活不显示

解决思路:

1. 所有的页面必须有index.vue

比如一个模块“日志和统计”, 它包含两个自己,‘操作日志’和‘数据列表’
日志和统计

  • LogsAndStatistics
    • OperationLog
      • index.vue
    • DataStatistics
      • index.vue
    • index.vue

对!必须有index.vue!必须有index.vue!!必须有index.vue!重要的事情3遍,不写就是不显示!!!
name也必须是一 一对应的唯一值!!!

2. 修改配置条件

  1. 先登录成功后后台会返回该账号匹配的路由信息,格式如下:
[
   {
       "title": "消息管理",
       "name": "message",
       "id": 2,
       "pid": 0,
       "icon": "el-icon-tickets",
       "component": "#",
       "path": "/message-management",
       "redirect": "/list",
       "alwaysShow": 1,
       "children": [
           {
               "title": "消息列表",
               "name": "MessageManagement",
               "id": 3,
               "pid": 2,
               "component": "MessageManagement",
               "path": "list"
           }
       ]
   },
       {
        "title": "客户管理",
        "name": "Customer:List",
        "id": 25,
        "pid": 0,
        "icon": "el-icon-user-solid",
        "component": "#",
        "path": "/customer",
        "redirect": "Customer",
        "alwaysShow": 1,
        "children": [
            {
                "title": "客户列表",
                "name": "CustomerManagement",
                "id": 26,
                "pid": 25,
                "component": "CustomerManagement",
                "path": "list"
            }
        ]
    },
    {
        "title": "用户和权限",
        "name": "",
        "id": 31,
        "pid": 0,
        "icon": "el-icon-user-solid",
        "component": "#",
        "path": "/user-permissions",
        "redirect": "/user-list",
        "alwaysShow": 1,
        "children": [
            {
                "title": "组织架构",
                "name": "OrganizationalStructure",
                "id": 37,
                "pid": 31,
                "component": "UsersAndPermissions/OrganizationalStructure",
                "path": "organizational-list"
            },
            {
                "title": "用户列表",
                "name": "UserList",
                "id": 32,
                "pid": 31,
                "component": "UsersAndPermissions/UserList",
                "path": "user-list"
            },
            {
                "title": "权限列表",
                "name": "PermissionList",
                "id": 41,
                "pid": 31,
                "component": "UsersAndPermissions/PermissionList",
                "path": "permission-list"
            },
            {
                "title": "角色列表",
                "name": "RoleList",
                "id": 44,
                "pid": 31,
                "component": "UsersAndPermissions/RoleList",
                "path": "role-list"
            }
        ]
    },
    {
        "title": "日志和统计",
        "name": "LogManagement",
        "id": 46,
        "pid": 0,
        "icon": "el-icon-error",
        "component": "#",
        "path": "/logs-statistics",
        "redirect": "/logs",
        "alwaysShow": 1,
        "children": [
            {
                "title": "操作日志",
                "name": "LogsAndStatistic",
                "id": 47,
                "pid": 46,
                "component": "LogsAndStatistics/OperationLog",
                "path": "logs"
            },
            {
                "title": "数据列表",
                "name": "DataStatistics",
                "id": 48,
                "pid": 46,
                "component": "LogsAndStatistics/DataStatistics",
                "path": "statistics"
            }
        ]
    }
]
  1. 先保存到本地:我们是登录成功后直接返回的如下图:
    在这里插入图片描述
// utils/auth.js
export function setPermission(permission){
  const permissionData = {permission}
	return localStorage.setItem(PERMISSION, JSON.stringify(permissionData))
}
export function getPermission(){
  const val = JSON.parse(localStorage.getItem(PERMISSION)|| '{}')
  return val.permission
}
  1. 我的permission配置文件直接copy的 vue-element-admin 的二次修改的。

首先是router下的index.js

import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)
export const constantRoutes = [
  {
    path: '/login',
    component: () => import('@/views/Login/index.vue'),
    hidden: true
  },
  {
    path: '/retrieve-password',
    component: () => import('@/views/RetrievePassword/index.vue'),
    hidden: true
  },
  {
    path: '/404',
    name:'Page404',
    component: () => import('@/views/404'),
    hidden: true
  }
]

const createRouter = () => new Router({
  isAddDynamicMenuRoutes: false, // 是否已经添加动态(菜单)路由
  scrollBehavior: () => ({ y: 0 }),
  routes: constantRoutes
})

const router = createRouter()
export function resetRouter() {
  const newRouter = createRouter()
  router.matcher = newRouter.matcher // reset router
}

export default router

然后修改src 目录下的permission.js

import router from './router'
import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
import { getToken,getPermission} from '@/utils/auth' // get token from cookie
import getPageTitle from '@/utils/get-page-title'

NProgress.configure({ showSpinner: false }) // NProgress Configuration

const whiteList = ['/login','/retrieve-password'] // 不需要重定向白名单:登录和找回密码页面不需要重定向

router.beforeEach(async(to, from, next) => {
  // start progress bar
  NProgress.start()

  // set page title
  document.title = getPageTitle(to.meta.title)

  // 确定用户是否已登录
  const hasToken = getToken()
  if (hasToken) {
    if (to.path === '/login') {
      // if is logged in, redirect to the home page
      next({ path: '/' })
      NProgress.done()
    } else {
      // 是否添加动态路由
      if (router.options.isAddDynamicMenuRoutes) {
        next()
      } else {
        try {
          // 获取本地存储的路由信息(后台返回的)
          const Permission = getPermission()
         if(Permission.length<1){ return Promise.reject('菜单数据加载异常')}
          const accessRoutes = await store.dispatch('permission/generateRoutes', Permission)
          router.addRoutes(accessRoutes)
          router.options.isAddDynamicMenuRoutes = true
          next({ ...to, replace: true })
        } catch (error) {
          console.log(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 {
    /* 未登录*/
    if (whiteList.indexOf(to.path) !== -1) {
      //在免费登录白名单中,直接进入
      next()
    } else {
      //没有访问权限的其他页面将重定向到登录页面。
      next(`/login?redirect=${to.path}`)
      NProgress.done()
    }
  }
})

router.afterEach(() => {
  NProgress.done()
})

store文件夹下添加permission.js (需要在store的index.js下引入:import permission from ‘./modules/permission’)

  • 解析返回的路由信息时import(‘@/views/XXX/index.vue’) 会报错,找不到。
  • 开始把整个路由信息’@/views/XXX/index.vue’全部返回,直接使用require([/${component}], resolve)) ,还是报错;
  • 搜索尝试后解决component只要中间部分:
    eg: `@/views/RetrievePassword/index.vue' => 'RetrievePasswod'
    解析时:require([`@/views/${component}/index.vue`], resolve))
import Vue from 'vue'
import {constantRoutes} from '@/router'
import Layout from '@/layout'
/**
* 后台查询的菜单数据拼装成路由格式的数据
* @param list 处理的路由列表
*/
export function AddMenuRoutes(list = []) {
  const newRoutes = []
  list.map((v, i) => {
    const {path,id,name,component,alwaysShow,redirect,title,icon,children} = v
    const route = {
      id,
      path: component=='#' && i==0?'/':path
    }
    if(component=='#'){ 
      Vue.set(route,'component',Layout)
    }else{
      Vue.set(route,'component',(resolve) => require([`@/views/${component}/index.vue`], resolve))
    }
    if(name){
      Vue.set(route,'name',name)
    }
    if(title){
      Vue.set(route,'meta',{title})
      if(icon){
        Object.assign(route.meta,{icon})
      }
    }
    if(alwaysShow==1){Vue.set(route,'alwaysShow',true)}
    if(redirect){Vue.set(route,'redirect',redirect)}
    if (children && children.length) {
      Vue.set(route,'children',[])
      route.children = AddMenuRoutes(v.children)
    }
    newRoutes.push(route)
  })
  return newRoutes
}

const state = {
  routes: [],
  addRoutes: []
}

const mutations = {
  SET_ROUTES: (state, routes) => {
    state.addRoutes = routes
    state.routes = constantRoutes.concat(routes)
  }
}

const actions = {
  /**
	 * @param {*} permissionList 后台传回来的路由数据
	 */
  async generateRoutes({ commit }, permissionList) {
    const MenuList = []
    const permissions = permissionList || []
    Object.assign(MenuList, permissions)
    const newRoutes = await AddMenuRoutes(MenuList)
    commit('SET_ROUTES', newRoutes)
    return newRoutes
  }
}

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

就可以看到效果了:
在这里插入图片描述

完整的authentic.js:

const TokenKey = 'access_token'
const PERMISSION ='Permission'
const USERINFO = 'UserInfo'
const BUTTONS = 'Buttons'
export function getUserInfo() {
  const val = JSON.parse(localStorage.getItem(USERINFO)||'{}')
  return  val.name
}
export function setUserInfo(name) {
  const userInfo={name}
  return localStorage.setItem(USERINFO, JSON.stringify(userInfo))
}
export function removeUserInfo() {
  return localStorage.removeItem(USERINFO)
}


export function getToken() {
  const val = JSON.parse(localStorage.getItem(TokenKey)|| '{}')
  return val.token
}
export function setToken(token) {
  const tokeData = {token}
  return localStorage.setItem(TokenKey, JSON.stringify(tokeData))
}
export function removeToken() {
  return localStorage.removeItem(TokenKey)
}

export function setPermission(permission){
  const permissionData = {permission}
	return localStorage.setItem(PERMISSION, JSON.stringify(permissionData))
}
export function getPermission(){
  const val = JSON.parse(localStorage.getItem(PERMISSION)|| '{}')
  return val.permission
}
export function removePermission() {
  return localStorage.removeItem(PERMISSION)
}

export function setButtons(buttons){
  const buttonsData = {buttons}
	return localStorage.setItem(BUTTONS, JSON.stringify(buttonsData))
}
export function getButtons(){
  const val = JSON.parse(localStorage.getItem(BUTTONS)|| '{}')
  return val.buttons
}
export function removeButtons() {
  return localStorage.removeItem(BUTTONS)
}

export function removeAllInfo() {
  removeButtons()
  removePermission()
  removeToken()
  removeUserInfo()
}


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值