当前位置: 首页 > news >正文

Vue3中基于路由的动态递归菜单组件实现

文章目录

  • 前言
  • 一、动态菜单的核心原理
  • 二、实现步骤详解
    • 1.定义路由配置
    • 2.创建递归菜单组件
    • 3.在父组件中使用动态菜单
  • 总结


前言

在现代Web应用中,动态菜单是提升用户体验的关键功能,尤其在后端管理系统或权限控制场景中。Vue 3结合Vue Router,可以轻松实现根据路由信息动态生成菜单,并通过递归组件封装成可复用的模块。本文将一步步指导你创建这样一个组件:组件外部传入路由信息,组件内部递归调用自身处理嵌套路由。整个过程结构清晰,代码可靠,适用于实际项目。


一、动态菜单的核心原理

动态菜单的核心是递归组件:菜单组件接收一个路由数组数据,使用v-for遍历每个路由项,路由path作为唯一标识,如果路由不包含子路由,直接生成菜单项;如果路由只包含一个子路由,将子路由作为菜单项;如果路由包括至少两个子路由,则先将路由meta信息中的标题作为菜单标题,再递归调用菜单组件,这样子菜单的生成就遵循前两种菜单生成规则来生成,直到生成全部菜单项。

二、实现步骤详解

1.定义路由配置

在项目中,路由信息通常在router/routes.js中定义。示例路由配置如下:

export const constantRoutes = [{path: '/login',component: () => import('@/views/login/index.vue'),name: 'login',meta: {title: '登录',hidden: true,},},{path: '/',component: () => import('@/layout/index.vue'),name: 'layout',meta: {title: '',hidden: true,},redirect: '/home',children: [{path: '/home',component: () => import('@/views/home/index.vue'),name: 'home',meta: {title: '首页',hidden: false,icon: 'HomeFilled',},},],},{path: '/screen',component: () => import('@/views/screen/index.vue'),name: 'screen',meta: {title: '数据大屏',hidden: false,icon: 'Platform',},},{path: '/acl',component: () => import('@/layout/index.vue'),name: 'acl',meta: {title: '权限管理',hidden: false,icon: 'Lock',},redirect: '/acl/user',children: [{path: '/acl/user',component: () => import('@/views/acl/user/index.vue'),name: 'user',meta: {title: '用户管理',hidden: false,icon: 'User',},},{path: '/acl/role',component: () => import('@/views/acl/role/index.vue'),name: 'role',meta: {title: '角色管理',hidden: false,icon: 'UserFilled',},},{path: '/acl/menu',component: () => import('@/views/acl/menu/index.vue'),name: 'menu',meta: {title: '菜单管理',hidden: false,icon: 'List',},},],},{path: '/product',component: () => import('@/layout/index.vue'),name: 'product',meta: {title: '商品管理',hidden: false,icon: 'Goods',},redirect: '/product/brand',children: [{path: '/product/brand',component: () => import('@/views/product/brand/index.vue'),name: 'brand',meta: {title: '品牌管理',hidden: false,icon: 'ShoppingCartFull',},},{path: '/product/attribute',component: () => import('@/views/product/attribute/index.vue'),name: 'attribute',meta: {title: '属性管理',hidden: false,icon: 'SetUp',},},{path: '/product/spu',component: () => import('@/views/product/spu/index.vue'),name: 'spu',meta: {title: 'SPU管理',hidden: false,icon: 'Suitcase',},},{path: '/product/sku',component: () => import('@/views/product/sku/index.vue'),name: 'sku',meta: {title: 'SKU管理',hidden: false,icon: 'CreditCard',},},],},{path: '/404',component: () => import('@/views/404/index.vue'),name: '404',meta: {title: '404',hidden: true,},},{path: '/:pathMatch(.*)*',redirect: '/404',name: 'notfound',meta: {title: 'notfound',hidden: true,},},
]

2.创建递归菜单组件

<script setup>import { useRouter } from 'vue-router'const router = useRouter()defineProps(['menuList'])const goRoute = (menuItem) => {router.push(menuItem.index)}
</script>
<script>export default {name: 'Menu',}
</script>
<template><!-- 根据路由动态递归生成菜单 --><templatev-for="item in menuList":key="item.path"><!-- 没有子菜单的菜单项 --><template v-if="!item.children"><el-menu-itemv-if="!item.meta.hidden":index="item.path"@click="goRoute"><el-icon><component :is="item.meta.icon"></component></el-icon><template #title><span>{{ item.meta.title }}</span></template></el-menu-item></template><!-- 只有一个子菜单的菜单项 --><template v-if="item.children && item.children.length === 1"><el-menu-itemv-if="!item.children[0].meta.hidden":index="item.children[0].path"@click="goRoute"><el-icon><component :is="item.children[0].meta.icon"></component></el-icon><template #title><span>{{ item.children[0].meta.title }}</span></template></el-menu-item></template><!-- 多个子菜单的菜单项 --><el-sub-menuv-if="item.children && item.children.length > 1":index="item.path"><template #title><el-icon><component :is="item.meta.icon"></component></el-icon><span>{{ item.meta.title }}</span></template><!-- 递归生成子菜单 --><Menu :menuList="item.children"></Menu></el-sub-menu></template>
</template>
<style scoped></style>

3.在父组件中使用动态菜单

<script setup>import Menu from './menu/index.vue'import { constantRoutes } from '@/router/routes.js'...
</script>
<template>
...<Menu :menuList="constantRoutes"></Menu>
...
</template>

总结

通过封装递归组件,Vue 3能高效实现动态菜单:外部传入路由信息,内部递归处理嵌套结构。这不仅减少了代码冗余,还提高了可维护性。在实际项目中,你可以根据需求扩展功能,如添加图标、权限校验等。

http://www.dtcms.com/a/427499.html

相关文章:

  • 建设主题网站的顺序一般是网站规划的案例
  • 免费网站建设制作上海网络推广报价
  • 手撕JS实现call,apply,bind
  • 【Java学习】类加载与实例化过程
  • [xboard] 19 kernel Makefile逐行分析1
  • 《足垒球百科》什么是足球、垒球、足垒球·垒球1号位
  • Process Monitor 学习笔记(5.1):Procmon 概述、抓取原理与常见用途
  • 重塑自然之美:朱小颜健康科技有限公司,开启非侵入式面部美学新时代
  • 站长工具关键词排名怎么查淘宝刷单网站制作
  • 做一个网站的详细教学建设通是正规网站吗
  • Redis Set 类型全解析
  • OpenSSH6 双库链接问题排查与解决总结
  • PyTorch实战车牌识别 小张的停车场项目逆袭之旅
  • IDEA 2025.2正式发布,AI能力有重大更新
  • 【Nginx开荒攻略】静态文件服务深度解析:MIME类型映射与优化实战
  • 郑州社交网站开发网推项目
  • 专做品牌网站手机微网站 模板
  • MQTT Dashboard 访问控制
  • 微算法科技(NASDAQ MLGO)研究基于信任场模型的异构物联网区块链分片算法,提高区块链的可扩展性
  • 数据结构13003考前急救
  • 教育门户网站建站工商登记查询网官网
  • 线代一轮复习
  • Qt解决不同线程,调用对方的函数
  • 开发避坑指南(60):Mysql导入数据报错ERROR 2006 (HY000) MySQL server has gone away解决方案
  • 手机网络不好怎么回事但信号是满的南宁百度seo优化
  • 网站建设怎样设置动态背景风景网站的制作
  • Java-138 深入浅出 MySQL Spring Boot 事务传播机制全解析:从 REQUIRED 到 NESTED 的实战详解 传播机制原理
  • Hadoop实战:从海量数据到AI决策的落地方法论
  • springboot+vue个人财务小程序(源码+文档+调试+基础修改+答疑)
  • 季休节能型遥测终端机RTU-为农业灌溉场景量身定制!