vue3后台管理系统实现动态侧边导航菜单管理(ElementPlus组件)

news2024/11/26 22:44:22

在这里插入图片描述

记住 一级(el-sub-menu)的都是只是展示的 点击跳转的都是一级下的子级(el-menu-item)
在这里插入图片描述

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

完整展示
在这里插入图片描述

1:在登陆功能进行登陆 获取menu列表
注册路由表的时候 把文件进行创建好 因为注册的方法需要获取这个路径
整个router下的main product等等都要创建

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

//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:侧边菜单界面

<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>

以上把侧边菜单展示实现了,, 但是实现跳转的话 路由表必须有相对应的路由

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/760008.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux--进程终止

一、进程终止时&#xff0c;操作系统做了什么&#xff1f;&#xff1f; 释放进程申请的相关内核数据结构和对应的代码和数据 本质就是释放系统资源&#xff08;最主要的资源是内存&#xff09; 二、进程终止的常见方式&#xff1f; a.代码跑完&#xff0c;结果正确 b.代码跑完&…

【我的2023上半年总结】感谢CSDN:第一次100w+阅读,赚大了!

大家好&#xff0c;这里是程序员晚枫。 因为工作一般都是996的原因&#xff0c;今天是2023上半年少有的周六休息日&#xff0c;正好看到平台的#2023年中总结#活动&#xff0c;赶紧来分享一下这半年的自媒体收获~ 主要说一些开心的事情 1、CSDN CSDN账号&#x1f449;Python…

MySQL的循环语句分析

1.while循环 复制 -- 设置mysql分隔符为//,也就意味着,当遇到下一个//时,整体执行SQL语句 DELIMITER //DROP PROCEDURE if EXISTS &lsquo;test&rsquo;; # 如果存在test存储过程则删除CREATE procedure test() # 创建无参存储过程,名称为testBEGIN DECLARE i I…

配置 Vite 的环境变量与模式 (.env mode)

目录 创建项目环境变量内建变量创建.env 文件定义变量HTML 环境变量替换 模式 创建项目 npm create vitelatest or yarn create vite or pnpm create vite 环境变量 Vite 在一个特殊的 import.meta.env 对象上暴露环境变量。 console.log(import.meta.env)内建变量 import.met…

关于chatGPT、AI绘画、AI提词器等AI工具国内如何使用

目前的AI潮流非常火热&#xff0c;OPENAI 出的CHATGPT可谓是目前大模型人工智能的代表&#xff0c;刚开始听说chatGPT可以写代码&#xff0c;写作&#xff0c;写方案&#xff0c;无所不能。还有AI绘画也很&#xff2e;&#xff22;作为一个程序员&#xff0c;为了体验这些&…

python+pytest接口自动化之参数关联

目录 一. 参数关联场景 二. 脚本编写 1. 在用例中按顺序调用 2. 使用Fixture函数 三. 总结 什么是参数关联&#xff1f; 参数关联&#xff0c;也叫接口关联&#xff0c;即接口之间存在参数的联系或依赖。在完成某一功能业务时&#xff0c;有时需要按顺序请求多个接口&…

听GPT 讲K8s源代码--pkg(三)

在 Kubernetes 项目中&#xff0c;pkg/controller目录下的子目录通常包含控制器相关的代码和逻辑。控制器是 Kubernetes 中用于管理资源的核心组件之一。它们负责监控资源的状态&#xff0c;并确保其符合所定义的期望状态。下面是对这些子目录的一些常见作用的解释&#xff1a;…

JavaScript中数据类型

对象和原始值 ● 在JavaScript中&#xff0c;有两种主要类型的数据&#xff0c;要不是原始值&#xff0c;要不是对象&#xff1b; 7种原始数据类型 1.数字 浮点数用于小数和整数。let age 23; 2.字符串 一系列字符的序列&#xff0c;用于文本。let firstName “IT知识…

全网最全整理,Allure集成Jenkins自动化测试实战(详细)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 Allure插件安装 …

libbpf-bootstrap 开发指南:概念与如何安装

目录 概念 如何安装& 使用 git 地址 使用git clone 下载代码 安装依赖环境 安装libbpf 编译example 概念 libbpf-bootstrap 是一个项目&#xff0c;旨在帮助开发者快速启动和开发使用 eBPF (Extended Berkeley Packet Filter) 和 libbpf 的程序。eBPF 是一种可以在…

2023.07.16 学习周报

文章目录 摘要文献阅读1.题目2.问题3.介绍4.Problem definition5.Method5.1 Feature Extractor5.2 Synthetic Node Generation5.3 Edge Generator5.4 GNN Classifier5.5 Optimization Objective5.6 算法 6.实验6.1 数据集6.2 基线6.3 实验结果 7.结论 数学建模1.欧式距离2.切比…

0130 物理层1

目录 2.物理层 2.1通信基础 2.1部分习题 2.物理层 2.1通信基础 2.1部分习题 1.下列说法正确的是&#xff08;&#xff09; A.信道与通信电路类似&#xff0c;一条可通信电路往往包含一个信道 B.调制是把模拟数据转换为数字信号的过程 C.信息传输速率是通信信道上每秒传…

SIP支持的传输协议

一、SIP支持的传输协议-UDP、TCP、TLS SIP是一个应用层的会话协议&#xff0c;与一般协议不同的是&#xff0c;SIP协议可以同时支持各种传输协议。 SIP支持UDP传输&#xff1a;UDP是一个无连接的协议&#xff0c;且不提供可靠性。在UDP上建立SIP连接存在不可靠性。 SIP…

【K210模块】使用UART模块发送和接收数据

官方案例链接 【K210模块】使用UART模块发送和接收数据 官方案例链接 一、代码部分1、添加转换句&#xff08;1&#xff09;字节data 转字符串① 添加了转换语句② 没有添加转换语句 &#xff08;2&#xff09;字符串str 转 字节data 2、三种方式的比较&#xff0c;K210发送到S…

图解Vit 2:Vision Transformer——视觉问题中的注意力机制

文章目录 Patch Embedding 回顾Seq2Seq中的attentionTransformer中的attention Patch Embedding 回顾 上节回顾 Seq2Seq中的attention 在Transformer之前的RNN&#xff0c;其实已经用到了注意力机制。Seq2Seq。 对于Original RNN&#xff0c;每个RNN的输入&#xff0c;都是对…

vue3项目创建(vite3+ts+elementui-plus)

文章目录 1.创建工程 1.创建工程 目的&#xff1a;vue3vitets 安装依赖&#xff0c;安装vite的工具 Vite下一代的前端工具链为开发提供极速响应v4.3 npm install -g create-vite创建工程 create-vite font-userui --template vue-ts –template vue-ts 后面的是配置模板&#…

CS 144 Lab Zero

CS 144 Lab Zero 环境搭建使用socket写一个网络程序In-memory reliable byte stream 对应课程视频: 【计算机网络】 斯坦福大学CS144课程 Lab 0 对应的PDF: Lab Checkpoint 0: networking warmup Lab 0 会省去Telnet部分内容。 环境搭建 Run Ubuntu version 22.10, then ins…

基于linux下的高并发服务器开发(第二章)- 2.3 进程创建

/*#include <sys/types.h>#include <unistd.h>pid_t fork(void)函数的作用&#xff1a;用于创建子进程返回值&#xff1a;fork()的返回值会返回两次。一次是在父进程中&#xff0c;一次是在子进程中在父进程中返回创建的子进程的ID&#xff0c;在子进程中返回0如何…

《微服务架构设计模式》第十三章 微服务架构的重构策略

微服务架构的重构策略 一、重构到微服务需要考虑的问题1、为什么重构2、重构形式3、重构策略 二、设计服务与单体的协作方式三、总结 一、重构到微服务需要考虑的问题 1、为什么重构 单体地狱造成的业务问题&#xff1a; 交付缓慢充满故障的软件交付可扩展性差 2、重构形式 …

itheima苍穹外卖项目学习笔记--Day6: 微信登录 / 商品浏览

Day6 a. HttpClientGET方式请求&#xff1a;POST方式请求&#xff1a; b. 微信登录 a. HttpClient HttpClient 是Apache Jakarta Common 下的子项目&#xff0c;可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包&#xff0c;并且它支持 HTTP 协议最新…