基于Element-Plus动态配置Menu 菜单栏

news2025/1/22 9:01:27

文章目录

  • 前言
  • 先看效果
    • 可兼容多级菜单栏(顺便配置多少级)
  • 一、新建组件
  • 二、使用步骤
  • 总结
    • `如有启发,可点赞收藏哟~`


前言

菜单栏配置化
图标配置化参考vite动态配置svg图标及其他方式集合


先看效果

可兼容多级菜单栏(顺便配置多少级)

在这里插入图片描述

一、新建组件

咱分为两个组件,一个母组件menu,还有个子组件sub-menu(兼容多级菜单,递归使用)

  • 新建 components/menu/index.vue
<script lang="ts" src="./index.ts"></script>

<template>
  <el-menu
    class="el-menu-demo"
    :default-active="activeIndex"
    :text-color="textColor"
    :active-text-color="activeTextColor"
    :background-color="bgColor"
    :mode="mode"
    :unique-opened="uniqueOpened"
    :collapse="collapse"
    :router="router"
    :ellipsis="ellipsis"
    @select="handleSelect"
  >
    <template v-for="item in menuList" :key="item + 'menu' + item.index">
      <SubMenu :menu="item"></SubMenu>
    </template>
  </el-menu>
</template>
  • 新建 components/menu/index.ts
import { computed, defineComponent } from "vue";
import type { MenuType } from "@/interface/index";
import { IndexHooks } from "@/composables";
import SvgIcon from "@/components/svg-icon/index.vue";
import { translateRouteTitle } from "@/lang";
import SubMenu from "./sub-menu/index.vue";
export default defineComponent({
  components: {
    SvgIcon,
    SubMenu,
  },
  props: {
    /**
     * 菜单列表
     */
    menuList: {
      type: Array<MenuType>,
      default: [
        {
          title: "菜单一",
          index: "0",
          icon: "document",
          subMenu: [
            {
              title: "子单一",
              icon: "document",
              index: "0-0",
              subMenu: [
                { title: "子单2.1", icon: "document", index: "0-0-0" },
                {
                  title: "子单2.1",
                  icon: "document",
                  index: "0-0-1",
                  subMenu: [
                    { title: "子单2.1.1", icon: "document", index: "0-0-1-0" },
                    { title: "子单2.1.2", icon: "document", index: "0-0-1-1" },
                  ],
                },
              ],
            },
            { title: "子单二", icon: "document", index: "0-1" },
          ],
        },
        {
          title: "菜单二",
          index: "1",
          icon: "document",
          subMenu: [
            { title: "子单一", icon: "document", index: "1-0" },
            { title: "子单二", icon: "document", index: "1-1" },
          ],
        },

        {
          title: "菜单三",
          index: "2",
          icon: "document",
        },
      ],
    },
    /**
     * 菜单展示模式
     */
    mode: {
      type: String,
      default: "vertical", // horizontal - 横向 / vertical - 纵向
    },
    /**
     * 是否水平折叠收起菜单(仅在 mode 为 vertical 时可用)
     */
    collapse: {
      type: Boolean,
      default: false,
    },
    /**
     * 是否省略多余的子项(仅在横向模式生效)
     */
    ellipsis: {
      type: Boolean,
      default: false,
    },
    /**
     * 菜单的背景颜色(十六进制格式)(已被废弃,使用--bg-color)
     */
    bgColor: {
      type: String,
      default: "#545c64",
    },
    /**
     * 文字颜色(十六进制格式)(已被废弃,使用--text-color)
     */
    textColor: {
      type: String,
      default: "#fff",
    },
    /**
     * 活动菜单项的文本颜色(十六进制格式)(已被废弃,使用--active-color)
     */
    activeTextColor: {
      type: String,
      default: "#ffd04b",
    },
    /**
     * 菜单高亮显示index
     */
    active: {
      type: String,
      default: "0-1",
    },
    /**
     * 是否只保持一个子菜单的展开
     */
    uniqueOpened: {
      type: Boolean,
      default: false,
    },
    /**
     * 是否启用 vue-router 模式。 启用该模式会在激活导航时以 index 作为 path 进行路由跳转 使用 default-active 来设置加载时的激活项。
     */
    router: {
      type: Boolean,
      default: false,
    },
  },
  setup(props, { emit }) {
    const activeIndex = computed({
      get: () => props.active,
      set: (val) => {
        emit("update:active", val);
      },
    });
    const { menuList } = props;
    const inDepthValueOfArray = (
      arr: Array<MenuType>,
      indexs: Array<string>
    ): Array<MenuType> | MenuType | undefined => {
      const index = Number(indexs[0]);
      if (indexs.length > 1) {
        const val = arr[index].subMenu;
        indexs.shift();
        return val && inDepthValueOfArray(val, indexs);
      } else if (indexs.length === 1) {
        return arr[index];
      } else {
        return arr;
      }
    };
    const { goTo } = IndexHooks();
    const handleSelect = (key: string, keyPath: string[]) => {
      if (!menuList) return;
      const indexs = key.split("-");
      activeIndex.value = indexs[0];
      const MenuType = inDepthValueOfArray(menuList, indexs);
      if (MenuType && !(MenuType instanceof Array)) {
        // goTo(MenuType?.path || "/", { t: new Date().getTime() });
      }
    };
    return {
      activeIndex,
      translateRouteTitle,
      handleSelect,
    };
  },
});

  • 新建 components/menu/sub-menu/index.vue
<script lang="ts" src="./index.js"></script>

<template>
  <el-sub-menu v-if="menu.subMenu" :index="menu.index">
    <template #title>
      <SvgIcon v-if="menu.icon" :icon-class="menu.icon" />
      {{ translateRouteTitle(menu.title) }}
    </template>
    <template
      v-for="subItem in menu.subMenu"
      :key="subItem + 'subItem' + menu.index">
      <SubMenu :menu="subItem" />
    </template>
  </el-sub-menu>
  <el-menu-item v-else :index="menu.index">
    <SvgIcon v-if="menu.icon" :icon-class="menu.icon" />
    {{ translateRouteTitle(menu.title) }}
  </el-menu-item>
</template>


  • 新建 components/menu/sub-menu/index.ts
import { defineComponent } from "vue";
import SvgIcon from "@/components/svg-icon/index.vue";
import { translateRouteTitle } from "@/lang";
export default defineComponent({
    name: "SubMenu",
    components: {
        SvgIcon,
    },
    props: {
        menu: {
            type: Object,
            required: true,
            default: {
                title: "子单一",
                icon: "document",
                index: "0-0",
                subMenu: [
                    { title: "子单2.1", icon: "document", index: "0-0-0" },
                    { title: "子单2.1", icon: "document", index: "0-0-1" },
                ],
            },
        },
    },
    setup() {
        return {
            translateRouteTitle,
        };
    },
});

二、使用步骤

咱直接以默认值做例子,具体数据可自定义,格式需以menu组件定义的,不然会报错

<script lang="ts" src="./index.ts" />

<template>
  <Menu />
  <!-- <Menu v-model:active="ctiHeaderMenuActive" :menuList="menuList" /> -->
</template>

import { defineComponent, reactive, ref } from "vue";
import Menu from "@/components/menu/index.vue";
export default defineComponent({
  components: {
    Menu,
  },
  setup() {
    return {
    };
  },
});


总结

如有启发,可点赞收藏哟~

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

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

相关文章

Vim 从何而来?

Vim 编辑器的创造者、维护者和终身领导者 Bram Moolenaar 为了纪念这位杰出的荷兰程序员&#xff0c;我们今天来聊一聊 Vim 的历史。 Vim 无处不在。它被很多人使用。同时 Vim 可能是世界上 “最难用的软件之一” &#xff0c;但是又多次被程序员们评价为 最受欢迎的 代码编辑…

耿明雨出席柬方70周年招待会晚宴

11月9日&#xff0c;庆祝柬埔寨独立和建军70周年欢迎晚宴上&#xff0c;全国政协副主席沈跃跃盛邀出席&#xff0c;此次招待会是由柬埔寨王国驻华大使馆主办&#xff0c;在北京励骏酒店圆满召开&#xff0c;晚宴现场&#xff1b;凯西索达大使致辞、中国外交部部长助理徐飞洪等领…

「Verilog学习笔记」使用8线-3线优先编码器Ⅰ实现16线-4线优先编码器

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 分析 当EI10时、U1禁止编码&#xff0c;其输出端Y为000&#xff0c;GS1、EO1均为0。同时EO1使EI00&#xff0c;U0也禁止编码&#xff0c;其输出端及GS0、EO0均为0。由电路…

HTML特殊字符对照码(避免字符乱码)

最近做了个vue项目&#xff0c;页面上写大于等于符号&#xff0c;小于等于符号的时候&#xff0c;总是出现乱码。特别让人头疼&#xff0c;后来查了资料&#xff0c;使用特殊字符的方式&#xff0c;能解决掉这个问题。所以将这些HTML 特殊字符对照码列出来&#xff0c;方便日后…

图解分布式事务实现原理(二)

参考 本文参考https://zhuanlan.zhihu.com/p/648556608&#xff0c;在小徐的基础上做了个人的笔记。 TCC 实现方案 TCC 概念简述 TCC&#xff08;Try-Confirm-Cancel&#xff09;是一种分布式事务处理模式&#xff0c;旨在保证分布式系统中的事务一致性。它的核心思想是将一…

3.5 Windows驱动开发:应用层与内核层内存映射

在上一篇博文《内核通过PEB得到进程参数》中我们通过使用KeStackAttachProcess附加进程的方式得到了该进程的PEB结构信息&#xff0c;本篇文章同样需要使用进程附加功能&#xff0c;但这次我们将实现一个更加有趣的功能&#xff0c;在某些情况下应用层与内核层需要共享一片内存…

这家提供数据闭环完整链路的企业,已拿下多家头部主机厂定点

“BEV感知数据闭环”已经成为新一代自动驾驶系统的核心架构。 进入2023年&#xff0c;小鹏、理想、阿维塔、智己、华为问界等汽车品牌正在全力推动从高速NOA到城区NOA的升级。在这一过程当中&#xff0c;如何利用高效的算力支撑、完善的算法模型、大量有效的数据形成闭环&…

【人工智能实验】A*算法求解8数码问题 golang

人工智能经典问题八数码求解 实际上是将求解转为寻找最优节点的问题&#xff0c;算法流程如下&#xff1a; 求非0元素的逆序数的和&#xff0c;判断是否有解将开始状态放到节点集&#xff0c;并设置访问标识位为true从节点集中取出h(x)g(x)最小的节点判断取出的节点的状态是不…

基于springboot实现医患档案管理系统项目【项目源码】计算机毕业设计

基于springboot实现医患档案管理系统演示 Java语言简介 Java是由SUN公司推出&#xff0c;该公司于2010年被oracle公司收购。Java本是印度尼西亚的一个叫做爪洼岛的英文名称&#xff0c;也因此得来java是一杯正冒着热气咖啡的标识。Java语言在移动互联网的大背景下具备了显著的…

03.智慧商城——封装请求模块、登录静态页面、图形验证码

01. 登录页静态布局 (1) 准备工作 新建 styles/common.less 重置默认样式 // 重置默认样式 * {margin: 0;padding: 0;box-sizing: border-box; }// 文字溢出省略号 .text-ellipsis-2 {overflow: hidden;-webkit-line-clamp: 2;text-overflow: ellipsis;display: -webkit-box…

【Spring】超详细讲解AOP(面向切面编程)

文章目录 1. 前言2. 什么是AOP3. AOP快速入门4. AOP的核心概念5. 切点表达式6. 切点函数7. 通知8. 总结 1. 前言 本文围绕AOP进行讲解,AOP可以做什么,涉及到了哪些注解,以及各个注解运行的时机,以及Around相较于其它注解有什么不同,并且如果要执行目标方法需要怎么做 2. 什么…

Java实现简单的俄罗斯方块游戏

一、创建新项目 1.首先新建一个项目&#xff0c;并命名为俄罗斯方块。 2.其次新建一个类&#xff0c;命名为Main&#xff0c;或其他的。 二、运行代码 代码如下&#xff1a; package 俄罗斯方块;import java.awt.BorderLayout; import java.awt.Color; import java.awt.Gr…

C# 字节数组按照指定大小拆分保存至TXT文件

1.按照4个字节拆分为一行显示示例代码 byte[] result new byte[] {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 };using (StreamWriter writer new StreamWriter("output.txt")){for (int i 0; i < result.Length; i 4) //按照四个字节拆分{byte[] tempArray n…

Android10 手势导航

种类 Android10 默认的系统导航有三种&#xff1a; 1.两个按钮的 2.三个按钮的 3.手势 它们分别对应三个包名 frameworks/base/packages/overlays/NavigationBarMode2ButtonOverlay frameworks/base/packages/overlays/NavigationBarMode3ButtonOverlay frameworks/base/packa…

【Python3】【力扣题】290. 单词规律

【力扣题】题目描述&#xff1a; 【Python3】代码&#xff1a; 1、解题思路&#xff1a;哈希。两个字典。分别记录字母对应的单词和单词对应的字母&#xff0c;若不是对应的&#xff0c;则返回False。 知识点&#xff1a;字符串.split()&#xff1a;将字符串按指定字符拆分成…

代码随想录算法训练营|五十三天

判断子序列 392. 判断子序列 - 力扣&#xff08;LeetCode&#xff09; 过程&#xff1a; public class Solution {public bool IsSubsequence(string s, string t) {int[,] dp new int[s.Length 1, t.Length 1];for (int i 1; i < s.Length; i) {for (int j 1; j <…

内置升压的单声道D类音频功率放大器:HT81293

HT81293是一款内置升压的单声道D类音频功率放大器&#xff0c;由锂电池供电时&#xff0c; THDN10%&#xff0c; 能连续输出18W功率&#xff08;4Ω负载&#xff09;。 HT81293A内置可动态调节的升压&#xff0c;可以提供一个适应不同输出功率的电压给D类功放&#xff0c;其可大…

1.mysql安装及基础

目录 概述安装上传jar包解压添加用户组和用户更改权限修改配置文件 my.cnf初始化登录mysql修改密码远程登录生效配置 sql语句分类数据定义语言 结束 概述 mysql安装及基础&#xff0c;后续涉及基础会继续补充。 安装 上传jar包 解压 tar -zxvf mysql-5.7.44-linux-glibc2.1…

六、Nacos快速入门

目录 一、服务注册到Nacos 二、nacos服务分级存储模型 1、作用 2、划分集群 3、根据权重负载均衡 三、环境隔离 1、在未设置namespace时&#xff0c;所有服务都默认在public 2、新建namespace 3、将order-service的namespace更改为dev 4、总结 一、服务注册到Nacos …

2019年五一杯数学建模C题科创板拟上市企业估值解题全过程文档及程序

2019年五一杯数学建模 C题 科创板拟上市企业估值 原题再现 科创板在首届中国国际进口博览会开幕式上宣布设立&#xff0c;是独立于现有主板市场的新设板块。设立科创板并试点注册制是提升服务科技创新企业能力、增强市场包容性、强化市场功能的一项资本市场重大改革举措&…