Vue3 background management system realizes dynamic side navigation menu management (ElementPlus component)

insert image description here

Remember that the ones at the first level (el-sub-menu) are all just displayed and clicked to jump to the sub-levels (el-menu-item) at the first level
insert image description here

insert image description here
insert image description here

full display
insert image description here

1: Create the file when logging in to obtain the menu list
and register the routing table with the login function, because the registration method needs to obtain this path, the
main product under the entire router, etc. must be created

insert image description here
insert image description here

//1:发送你的用户名和密码获取token和用户信息**
//2:拿着token获取菜单列表接口 (我的项目封装的axios  ,这里演示的话就写这么个意思 知道就行)**
 const userMenuData=await axios.get('xxxx'{
    
    'token':'xxxxx'}) 
 //3:保存在 vuex中
 //4:把菜单权限注入到路由表内
 
 const  mapMenusToRouters=(userMenus: any[])=> {
    
    
    console.log(userMenus, 'userMenus')
    // type==1说明有二级 type==2 就是二级
    // 保存处理好的路由。
    const routes: RouteRecordRaw[] = [];
    // 获取所有的路由文件
    const allRoutes: RouteRecordRaw[] = [];
    // 1先查询路由目录文件 获取main下的ts文件 
    const routeFiles = require.context('../router/main', true, /\.ts/)
    // 2  获取keys()  引入文件
    routeFiles.keys().forEach(key => {
    
    
        // 3切割文件./  .ts  
        const route = require('../router/main' + key.split('.')[1])
        // 4  把文件追加到数组 allRoutes中
        allRoutes.push(route.default)
    });
    const _recurseGetRoute = (menus: any[]) => {
    
    
        for (const menu of menus) {
    
    
            if (menu.type == 1) {
    
    
                _recurseGetRoute(menu.children ?? [])
            } else {
    
    
                // type==2  没有了子集
                const route = allRoutes.find((route) => {
    
    
                    return route.path == menu.url
                })
                if (route) {
    
    
                    routes.push(route)
                } 
            }
        }
    }  
    _recurseGetRoute(userMenus)
    if (routes) {
    
    
        return routes

    } else {
    
    
        return []

    }

}
 //记得 import {useStore}  from 'store';
   const store = useStore(); 
  const userMenu = computed(() => {
    
    
    return store.state.login.userMenus;
 });  
 //调用函数进行处理
const routes = mapMenusToRouters(userMenus)
  //放在router.ts的main 下的children中=========>路由表注册完毕
routes.forEach((key: RouteRecordRaw) => router.addRoute('main', key)  )

2: Side menu interface

<template>
  <div class="nav-menu">
    <div class="logo">
      <img class="img" src="~@/assets/img/logo.svg" alt="logo" />
      <span class="title" >vue3+ts</span>
    </div>
     
    <el-menu
      :default-active="dafaultValue"
      background-color="#0c2135"
      text-color="#b7bdc3"
      :collapse="isCollapse"
      active-text-color="#0a60bd"
      class="el-menu-vertical"
    >
      <template v-for="item in userMenu" :key="item.id">
      
        <template v-if="item.type == 1">
          <el-sub-menu :index="item.id + ''">
            <template #title>
              <el-icon><Platform /></el-icon>
              <span>{
    
    {
    
     item.name }}</span>
            </template>
            <template v-for="subItem in item.children" :key="subItem.id">
              <el-menu-item
                :index="subItem.id + ''"
                @click="handleMenuItemClick(subItem)"
              >
                <template #title>
                  <el-icon><Platform /></el-icon>
                  <span>{
    
    {
    
     subItem.name }}</span>
                </template>
              </el-menu-item>
            </template>
          </el-sub-menu>
        </template>
        <template v-else-if="item.type === 2">
          <el-menu-item :index="item.id + ''">
            <span>{
    
    {
    
     item.name }}</span>
          </el-menu-item>
        </template>
      </template>
    </el-menu>
  </div>
</template>
<script setup lang="ts">
import {
    
     useRouter, useRoute } from "vue-router";
 import {
    
     useStore } from "@/store/index";
 
//1:vuex获取菜单列表   
  const store = useStore(); 
  const userMenu = computed(() => {
    
    
    return store.state.login.userMenus;
 }); 
 //2:点击el-menu-item上的按钮跳转的函数
 const router = useRouter();
 const handleMenuItemClick = (item: any) => {
    
    
 // item.url不存在就跳转到自己定义的界面 比如404 (/not-found)
  router.push({
    
     path: item.url ?? "/not-found" });
};
//3:  el-sub-menu上有一个属性是dafaultValue
//  意思是默认选择的路由菜单 不能写死 不然我刷新的时候 就不能显示当前的选中菜单,而是选中写死的菜单
//  比如 我写死的dafaultValue是用户管理,当前点击菜单管理进行刷新数据的时候 他会跑到用户管理里面 这是错误的

const pathMapToMenus = (userMenu: any[], currentPath: string): any => {
    
    
    for (const menu of userMenu) {
    
    
        // 如果type==1  那么就是含有二级
        if (menu.type == 1) {
    
    
            console.log(menu)
            // 调用函数本身 把结果返回给我
            const findMenu = pathMapToMenu(menu.children ?? [], currentPath)
            if (findMenu) {
    
    
                return findMenu
            }
            // 如果type==2    那么直接判断后把结果返回给我
        } else if (menu.type == 2 && currentPath == menu.url) {
    
    
            console.log(menu, '2')
            return menu
        }
    }
}
  const route = useRoute();
  const currentPath = route.path;
  const menu = pathMapToMenu(userMenu.value, currentPath);
  const dafaultValue = ref(menu.id + "");
</script>

The display of the side menu is realized above, but the routing table must have a corresponding route to realize the jump

router/index.ts

import {
    
     createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
import {
    
     accountLoginRequest, RequestUserInfoByid, RequestUserMenusByRoleId } from '@/service/login/login'; 
const routes: Array<RouteRecordRaw> = [
  {
    
    
    path: '/',
    redirect: '/main'
  },
  {
    
    
    path: '/login',
    name: 'login', 
    component: () => import(/* webpackChunkName: "about" */ '../views/login/login.vue')
  },
  {
    
    
    path: '/main',
    name: 'main', 
    redirect:'/main/system/user',
    component: () => import(/* webpackChunkName: "about" */ '../views/main/main.vue'),
    children:[]
  },
   {
    
    
   //404请求不存在的路径
    path: '/:pathMatch(.*)*',
    component: () => import('@/views/not-found/not-found.vue')
  }
]

const router = createRouter({
    
    
  history: createWebHashHistory(),
  routes
})
// 导航守卫
router.beforeEach((to) => {
    
    
  if (to.path !== '/login') {
    
    
    const token = window.localStorage.getItem('token')
    if (!token) {
    
    
      return '/login'
    }  
  } 
})
console.log(router, 'router')
export default router

Guess you like

Origin blog.csdn.net/weixin_45441173/article/details/131738980