后台所传数据生成,动态路由

894 阅读2分钟

一.先设置生成路由的格式

  1. 假设业务路由放在 @/view/,路由文件结构模式如图(其中menuManage与userManage为业务路由):在这里插入图片描时12312述
// router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
//1.基础路由
const basicRoutes=[
  {
        path: '/',
        redirect: '/index',
    },

    {
        path: '/index',
        name: 'index',
        meta: { isBanner: true },
        component: () => import('@/views/home/index.vue'),
    },
    {
        path: '/login',
        name: 'login',
        meta: { isBanner: true },
        component: () => import('@/views/login/login.vue'),
    },]
//2.创建路由
function createRouter() {
    return new VueRouter({
        mode: 'hash',
        scrollBehavior: () => ({ y: 0 }),
        routes: basicRoutes,
    })
}
const router = createRouter()
//3.初始路由
export const resetRouter = () => {
    router.matcher = createRouter().matcher
}
//4.路由导航
router.beforeEach((to, from, next) => {
    const beforeLoginRoutes = ['index', 'login']
    const loginRefuse = ['/login']
    //这可以换成token
    const isLogin = sessionStorage.getItem('isLogin')
    if (isLogin) {
        if (loginRefuse.indexOf(to.path) !== -1) {
            console.log('登录后拒绝', to.path)
            next(false)
        } else {
            console.log('登录后', to.name)
            next()
        }
    } else {
        if (beforeLoginRoutes.includes(to.name)) {
            console.log('登录前正常', to.name)
            next()
        } else {
            console.log('登录前拒绝', to.name)
            next('/login')
        }
    }
})
export default router
// 额外路由(详情页编辑页等等)-----可另写js存放,这里为图方便
export const extraRoutes = {
    manageCenter: [
        {
         path: `/manageCenter/menuManage/menuManageDetail`,
         component: () => import(`@/views/manageCenter/menuManage/menuManageDetail.vue`),
           name: 'menuManageDetail',
           meta: {
              // 在某个激活页面跳到属于该页面的详情页,保持激活状态不变(通过此值判断)
             activeUrl: 'menuManage',
           },
        },
    ],
}


二. 在store的perims.js中获取后台数据并生成路由

//store/perims.js
import vueRouter from '../../router'
import { resetRouter } from '../../router'
import { extraRoutes } from '../../router'

 function deep(list, keyName) => {
    let newList = []
    for (let i = 0, leng = list.length; i < leng; i++) {
        if (list[i][keyName] && list[i][keyName].length > 0) {
            const data = deep(list[i][keyName], keyName)
            newList.push(...data)
        } else {
            newList.push(list[i])
        }
    }
    return newList
}

const index={
 state: {
        // 处理过后的路由
        menuData: {},
        // 切换的展示菜单
        showMenuData: [],
        topMenuData: ['index'],
    },
        mutations: {
        SET_MENU(state, data) {
            state.menuData = data
        },
        SET_SHOWMENU(state, data) {
            state.showMenuData = data
        },
       //2.1. 将路由动态生成,可根据后端数据自定义meta
        SET_PERMISSION(state, router) {
            //动态添加路由
            if (router.route.length == 0) {
                return
            }
            //生成子路由
            const listRoutes = router.route.map((item) => {
                return {
                    path: `/${router.routeType}/${item.permitUrl}`,
                    component: () => import(`@/views/${router.routeType}/${item.permitUrl}/index.vue`),
                    name: item.permitUrl,
                    meta: { activeUrl: item.permitUrl, routeType: router.routeType },
                }
            })
            // 生成顶部路由,并将对应子路由嵌进去
            const routes = [
                {
                    path: `/${router.routeType}`,
                    component: () => import(`@/views/${router.routeType}/index.vue`),
                    redirect: `/${router.routeType}/${router.route[0].permitUrl}`,
                    children: listRoutes.concat(extraRoutes[router.routeType]),
                },
            ]
            vueRouter.addRoutes(routes)
        },
    },
     actions: {
     // 4. 可在顶部路由点击中调用此函数,切换菜单
        setShowMenuData({ commit, state }, topType) {
            // 存储菜单类别
            sessionStorage.setItem('topType', topType)
            commit('SET_SHOWMENU', state.menuData[topType])
        },
        // 1.在登录后调用该函数
        getPermisson({ commit, state }) {
         	//重置路由到初始
         	//(若是通过接口频繁切换生成菜单可使用,防止生成重复路由,若是一次性生成路由没必要)
            // resetRouter()
            //后端传的数据格式如下(注意其中的一级数据为顶部路由,通过切换顶部路由,切换菜单)
            let menuRoute = [
                  {
                     permitName: '管理中心',
                     permitUrl: 'manageCenter',
                     showName: '管理中心',
                     subList: [
                       {
                         permitName: '菜单管理',
                         permitUrl: 'menuManage',
                         showName: '菜单管理',
                         icon: 'menuIcon_moneyExcel'},
                        {
                         permitName: '用户管理',
                         permitUrl: 'userManage',
                         showName: '用户管理',
                         icon: 'userManage'}
            ]
            let menuData = {}
              menuRoute.forEach((item) => {
                        menuData[item.permitUrl] = item.subList
                        // 动态获取顶部路由
                        state.topMenuData.push(item.permitUrl)
                        //2.0 动态生成路由,其中的deep是将后台传过来的路由 递归过滤出来
                        commit('SET_PERMISSION', { routeType: item.permitUrl, route: deep(item.subList, 'subList') })
                    })
                    // 3.存储过滤后的菜单数据格式
                    commit('SET_MENU', menuData)
        },
}


总结

若要在刷新页面保持菜单数据,可以将获取数据的接口放在App.vue的created函数里,并判断在用户已登录状态下获取菜单数据。这样可以不用将菜单数据存在本地,其用户信息类似。

注意:这里的方式适用于后台管理类的系统,若想扩展,思路类似,敬请探索。若有BUG,欢迎指正