项目总结:项目中动态路由 动态菜单具体实现

676 阅读2分钟

项目中菜单路由的动态搭建

1、请求接口getMenu(在beforeEach中请求)

router目录下index.js 封装路由公用及静态路由部分
import Vue from "vue";
import Router from "vue-router";
import Layout from "@/views/layout/Layout";
Vue.use(Router);
export const constantRouterMap = [
  {
    path: "/401",
    component: () => import("@/views/error-page/401"),
    hidden: true
  },
  {
    path: "/404",
    component: () => import("@/views/error-page/404-new"),
    hidden: true
  },
  {
    path: "/305",
    component: () => import("@/views/error-page/305"),
    hidden: true
  }
];

export default new Router({
  mode: "history", // require service support
  // 浏览器回退,切换路由时默认滚动的位置
  scrollBehavior: () => ({
    y: 0
  }),
  routes: constantRouterMap
});
封装动态路由及菜单数据部分
import router from "./router";// 引入router的公用及静态页面部分
import store from "./store"; //引入 vuex
import { getMenu } from "./api/login"; //封装过axios的方法
// 在router.beforeEach中进行 菜单的请求
router.beforeEach((to, from, next) => {

let res = getMenu({
   	// 入参
    });
const arr = res.data.data //请求后的菜单数据
let menuArr = parseJsonMenu(arr) //parseJsonMenu 处理数据以得到适用于菜单的方法 这个方法需要自己封装

const routeObj =JSON.parse(JSON.stringify(arr));// 进行深拷贝避免相互影响

store.dispatch("generateRoutes", routeObj).then(() => { //更改vuex中动态路由的数据状态
        router.addRoutes(store.getters.addRouters); // 动态添加可访问路由表
        next({
          ...to,
          replace: true
        }); // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
      });
      
store.dispatch("setMenu", menu); //更改vuex中动态菜单的数据状态
// 路由守卫其他操作都可以这里处理
})

vuex中的 generateRoutes

import { constantRouterMap } from "@/router";
const _PERMISSION = {
  state: {
    routers: constantRouterMap,
    addRouters: []
  },
  mutations: {
    setRouters: (state, routers) => {
      state.addRouters = routers;
      // 和已经存在的路由表拼接
      state.routers = constantRouterMap.concat(routers);
      state.routers.push({ path: "*", redirect: "/" });
    }
  },
  getters: {
    addRouters: state => {
      return state.addRouters;
    }
  },
  actions: {
    generateRoutes({ commit }, response) { // 路由数据处理
      let asyncRouters = filterAsyncRouter(response) //自己封装的数据处理方法
      asyncRouters.push({ path: "*", redirect: "/404", hidden: true });

      const routers = [];
      asyncRouters.forEach(item => {
        if (item.children && item.children.length) {
          let arr = [];
          item.children.forEach(itemSub => {
            arr = arr.concat(itemSub.children);
          });
          item.children = arr;
        }

        routers.push(item);
      });
      commit("setRouters", routers);
    }
  }
};

function filterAsyncRouter(routers) {
  // 遍历后台传来的路由字符串,转换为组件对象
  let accessedRouters = routers.filter(router => {
    // 路由数据处理
  });
  return accessedRouters;
}
function loadView(view) {  // 封装路由懒加载
  return () => import(`@/views/${view}`);
}

function getRedirect(sons) { //重定向过滤判断 默认打开是得到的第一个路由
  // 重定向过滤 不同项目数据判断不通
  if(){
  return getRedirect(sons[0].sons);
  }
}

export default _PERMISSION;

菜单也同样用vuex进行存储 【这里不详细写了】