vue3+vite 动态侧边栏+面包屑+当前栈的访问路由

效果图
在这里插入图片描述

  1. 在本示例管理系统中,由于每个用户的权限不一样,拥有的可以访问的路由页面也不一样。
  2. 用户能访问的路由页面都是后端根据权限动态配置的。
  3. 我们前端需要根据后端接口返回的路由表去动态增删路由,从而生成这个用户所拥有的路由。

permission.js

import store from "@/store";
import router from "./router";
import { getPermissionList, routerPackage } from "@/utils/permission";
import { Session } from "@/utils/cache";

// 获取菜单权限tree树
const loadAsyncRoutes = async () => {
  const menuList = await getPermissionList();
  let routesList = routerPackage(menuList);
  routesList.forEach((route) => {
    router.addRoute("HOME", route);
  });
};
router.beforeEach(async (to, from, next) => {
  // 开启进度条
  store.commit("menu/set_Loading", true);
  if (Session.get("token")) {
    // 解决路由刷新出现空白
    if (store.state.menu.menuList.length == 0) {
      try {
        await loadAsyncRoutes();
        // 如果 addRoutes 并未完成,路由守卫会一层一层的执行执行,直到 addRoutes 完成,找到对应的路由
        next({ ...to, replace: true });
      } catch (error) {
        next();
      }
    } else {
      let curRoute = router.getRoutes().filter((item) => item.path == to.path);
      if (curRoute.length && curRoute[0].components.default) {
        document.title = to.name;
        next();
      } else {
        next("/404");
      }
    }
  } else {
    if (to.path == "/login") {
      next();
    } else {
      next("/login");
    }
  }
});

// 后置关闭进度条
router.afterEach(() => {
  store.commit("menu/set_Loading", false);
});

utils/permission.js

//获取菜单权限tree树
export const getPermissionList = async () => {
  let list = await getMenuTreeList();
  if (list) {
    store.commit("menu/set_MenuList", list);
  }
  // const menuList = packageMenuList(list); //开启过滤权限数组
  return list;
};

// 路由组成一
export function routerPackage(menuList) {
  const modules = import.meta.glob("../views/**/*.vue");
  return menuList.filter((route) => {
    if (route.component?.length) {
      route.component = modules["../views" + route.component + ".vue"];
    } else {
      route.component = () => import("@/components/layout/RouteView.vue");
    }
    if (Array.isArray(route.children) && route.children.length) {
      route.children = routerPackage(route.children);
    }
    return true;
  });
}

// 路由组成二(使用改方法且修改 src/permission.js文件)
// export const routerPackage = (routerMap, parent) => {
//   const modules = import.meta.glob("../views/**/*.vue");
//   return routerMap.map((item) => {
//     const currentRouter = {
//       path: item.path,
//       name: item.name,
//       meta: {
//         title: item.name,
//         icon: item.icon || null,
//       },
//     };
//     //验证父路由为空
//     if (item.component?.length) {
//       currentRouter.component = modules["../views" + item.component + ".vue"];
//     } else {
//       currentRouter.component = () =>
//         import("@/components/layout/RouteView.vue");
//     }
//     // 是否有子菜单,并递归处理
//     if (item.children?.length) {
//       currentRouter.children = routerPackage(item.children, currentRouter);
//     }
//     return currentRouter;
//   });
// };

面包屑BreadCrumb

<template>
  <a-breadcrumb>
    <a-breadcrumb-item v-for="(item, index) in listBread" :key="item.path">
      <span v-if="index == 0">{{ item.name }}</span>
      <router-link v-else :to="item.path">{{ item.name }}</router-link>
    </a-breadcrumb-item>
  </a-breadcrumb>
</template>

<script setup>
import { ref } from "@vue/reactivity";
import { watchEffect } from "@vue/runtime-core";
import { useRoute } from "vue-router";

const listBread = ref([]);
const route = useRoute();

// 监听路由变化
watchEffect(() => {
  listBread.value = route.matched;
});
</script>

MultiTab文件(记录栈访问路由)暂不更新

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值