vue动态路由来生成系统菜单(一)

先说下功能吧,就是菜单通过动态路由进行渲染出来,而不是路由配置写死来实现。虽然网上已经有各种帖子来介绍,但我还是折腾了快2天才搞定。逻辑非常简单,思路也简单就是从数据库查下路由配置信息,构建成路由结构交给addRoutes。最要命的是require赖加载不支持变量,折腾一天才搞出来。

直接上代码吧







关键就是这句话,来动态构建路由

           //动态添加路由信息
            DynamicRouterUtils._loadRouters(menus, vueObj, UnitTabSetHomePage);

DynamicRouterUtils的代码如下

import  Error404 from '../../sysPage/system/Error404';


//从menus里面过滤出页面信息
function _getPagesFromMenus(menus, pages) {
  if (AssertUtils.isNotNull(menus)) {
    menus.forEach(function (item, index) {
      if (item.type === "page") {
        pages.push(item);
      }
      if (AssertUtils.isNotNull(item.children) && AssertUtils.isArray(item.children)) {
        _getPagesFromMenus(item.children, pages);
      }
    })
  }
}
function getViews(path) {
  path=path.replace(".vue","")+".vue";
  path = path.replace("/pages", ".");
  let context = require.context('@/pages', true, /^\/*.*\.vue/);
  return resolve => {
    require.ensure([], (require) => {
      resolve(context(path))
    })
  }
}



var getLastUrl=(str,yourStr)=>str.slice(str.lastIndexOf(yourStr))//取到浏览器出现网址的最后"/"出现的后边的字符
//根据菜单生成路由
function _getRouters(menus) {
  let pages = [];
  _getPagesFromMenus(menus, pages);
  const aRouter = [];let routerUrls=[];let routerJsons={};
  pages.forEach(function (item, index) {
    let {id, componentUrl, moduleName, name, url, children}=item;
    //如果是存在 组件url 才需要生成路由配置 而且url是/开头的
    const oRouter = {
      path: url,
      componentUrl:componentUrl,
      component: getViews(componentUrl),
      name: url,
      id: id
    }
    aRouter.push(oRouter);
    routerJsons[getLastUrl(url,'/')]=oRouter;
    routerUrls.push(getLastUrl(url,'/'));
  })
  StorageUtils.addSessionItem("routerUrls", routerUrls.join(";"));
  StorageUtils.addSessionItem("routerJsons", JSON.stringify(routerJsons));
  return aRouter;
}
const constantRouterMap = [
    //404
  {path: '/404',component: Error404},{ path: '*', redirect: '/404' }//重定向到404
]
export default {
  getRouterByUrl(lastUrl,UnitTabSetHomePage,router){
    let routerJsons=JSON.parse(StorageUtils.getSessionItem("routerJsons"));
    let routerObj=routerJsons[lastUrl];
    //根据组件的url 来获取组件对象
    let {componentUrl}=routerObj;
    routerObj["component"]=getViews(componentUrl);
    if(AssertUtils.isNotNull(routerObj)){
      router.addRoutes( constantRouterMap.concat([
        {
          path: '/UnitTabSetHomePage',
          name: "tabSetHomePage",
          component: UnitTabSetHomePage,
          children: [routerObj]
        }]))
    }
    return routerObj;
  },
  //动态加载相应的路由 根据菜单信息
  _loadRouters(menus, vueObj, UnitTabSetHomePage) {
    //根据菜单获取路由信息
    let routers = _getRouters(menus);
    //动态添加路由信息
    if (AssertUtils.isNotNull(routers) && AssertUtils.isArray(routers)) {
      vueObj.$router.addRoutes(constantRouterMap.concat([
        {
          path: '/UnitTabSetHomePage',
          name: "tabSetHomePage",
          component: UnitTabSetHomePage,
          children: routers
        }]));
    }
  }
}


大家千万别去研究require(变量)这种方式了,我都折腾了一天,各种法子都试了,没一个是可以用的,还是通过require.context 去取吧。虽然可能性能不是最佳的,但总比写死路由来的可靠。由于本人的git还没弄好,后续我会把项目放到git上去,目前需要代码的可以qq【289028210】我。

到这并没有完全搞定,你会发现去刷新子界面的时候页面是空白。没法点击f5去刷新了,而且在子路由界面下,修改操作后界面也是空白,请看下一节对这个进行处理。

你可能感兴趣的:(vue)