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

vue 专栏收录该内容
39 篇文章 2 订阅

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

直接上代码吧

<template>
  <div class="go-page go-manage-page">
    <!--头部-->
    <ManageHeader moduleName="UnitTabSetHomePage" :routerId="manageRouterId" :tabsetId="adminTabsetId"
                  :userName="userName"></ManageHeader>
    <!--左侧菜单-->
    <ManageLeftMenu :menuState="menuState" :menus="menus" :routerId="manageRouterId"
                    :tabsetId="adminTabsetId"></ManageLeftMenu>
    <!--tabset区块-->
    <AdminTabset :menuState="menuState" :winResize="winResize" :id="adminTabsetId" :routerId="manageRouterId"
                 :defaultPage="adminMainPageId"></AdminTabset>

    <!--首页内容-->
    <div :id="adminMainPageId" style="display: none">
      <AdminMainPage :tabsetId="adminTabsetId" :routerId="manageRouterId" :menus="menus"></AdminMainPage>
    </div>

    <!--隐藏路由-->
    <div style="visibility: hidden;position: absolute;left: 0;top:0;" class="h100b" :id="manageRouterId">
      <router-view class="h100b router-view"></router-view>
    </div>

    <HomePageWinArea></HomePageWinArea>
  </div>
</template>

<script>
  import {mapState, mapActions} from 'vuex'
  import AdminMainPage from '../commonComponents/AdminMainPage';
  import ManageHeader from '../commonComponents/ManageHeader';
  import ManageLeftMenu from '../commonComponents/ManageLeftMenu';
  import AdminTabset from '../commonComponents/AdminTabset';
  import HomePageWinArea from '../commonComponents/HomePageWinArea';
  import  UnitTabSetHomePage from '../../../pages/manageHomePage/UnitTabSetHomePage';
  import  DynamicRouterUtils from '../commonJs/dynamicRouterUtils.js';


  GoingUtils.mainHeight = $(document.body).height() - 78;
  export default {
    created: function () {
      let vueObj = this;
      //从缓存中获取到当前用户的菜单信息
      let unitManageMenus = StorageUtils.getSessionItem("unitManageMenus"); 
      if (AssertUtils.isNotEmpty(unitManageMenus)) {
        let menusTemp = JSON.parse(unitManageMenus);
        vueObj.$store.commit($M('SET_MENUS', 'UnitAdminStore'), menusTemp);
//        加载路由
        DynamicRouterUtils._loadRouters(menusTemp, vueObj, UnitTabSetHomePage);
      } else {
        //如果缓存中不存在 则从数据库中查询出用户的菜单信息
        let queryCommand = new QueryCommand("/go-framework/menu/queryMenuAclInfo/erp");
        //执行查询操作
        queryCommand.executeAsyncQuery({}, function (backData) {
          if (backData != null) {
            let secondItems = backData[0].children;
            let menus = backData[0].children;
            vueObj.$store.commit($M('SET_MENUS', 'UnitAdminStore'), menus);
            //缓存起来
            StorageUtils.addSessionItem("unitManageMenus", JSON.stringify(menus));
            //动态添加路由信息
            DynamicRouterUtils._loadRouters(menus, vueObj, UnitTabSetHomePage);
          }
        }, () => {
        }, "json");
      }
    },
    name: 'homePage',
    computed: {
      //tabset对象的id
      adminTabsetId(){
        return "unitTabSetHomePage"
      },
      //默认首页div的id
      adminMainPageId(){
        return GoingUtils.getUUid();
      },
      //路由div的id
      manageRouterId(){
        return GoingUtils.getUUid();
      },
      ...mapState({
        winResize: state => state.UnitAdminStore.winResize,
        menuState: state => state.UnitAdminStore.menuState,
        menus: state => state.UnitAdminStore.menus,
        userName: state => state.UnitAdminStore.userName,
      })
    },
    mounted(){
      $.getScript("/static/plugin/Sortable.js", function () {

      });

      let vueObj = this;
      //加载当前用户信息
      this.$store.dispatch('getCurrentUser', function (backData) {
        vueObj.$store.commit($M("GET_CURRENT_USER", "UnitAdminStore"), backData);
      });

      //将routerId缓存起来
      this.$store['mainRouterId'] = this.manageRouterId;

      //如果界面大小发生变更
      $(window).resize(function () {
        //修改state状态,触发控件变化
        vueObj.$store.commit($M('SET_WIN_RESIZE', 'UnitAdminStore'));
      });
      //设置滚动条样式
      $(".dhx_cell_cont_tabbar").css("overflow", 'auto')
    },
    beforeDestroy(){

    },
    components: {
      HomePageWinArea,
      AdminMainPage,
      ManageHeader,
      ManageLeftMenu,
      AdminTabset,
    }
  }
</script>



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

           //动态添加路由信息
            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去刷新了,而且在子路由界面下,修改操作后界面也是空白,请看下一节对这个进行处理。

  • 1
    点赞
  • 1
    评论
  • 10
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

评论 1 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

飞天代码

你的鼓励将是我一如既往的动力。

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值