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

Vue3 Router高级用法—菜单动态渲染

        在许多系统中,通常都需要设计菜单栏,而菜单栏的选项是基于路由渲染的,如果将菜单栏写死,那么需要增加新菜单时,需要修改菜单栏代码,这就比较麻烦,因此可以对菜单栏进行封装,基于路由动态渲染菜单栏,这样只需要添加新的路由即可(这是必要操作)。

1 定义路由规则

import { createRouter, createWebHistory } from 'vue-router'
// 创建路由实例
const router = createRouter({// 路由模式:历史模式,特点是路由后面不带#号history: createWebHistory(),// 在这个数组中进⾏路由规则的详细配置routes: [{// 根路径(根路径重定向到/login路径)path: '/',redirect: '/login'},{// 登录页path: '/login',component: () => import('@/views/login/index.vue')},{// 系统主⻚path: '/',component: () => import('@/layout/index.vue'),// 路由嵌套(二级路由)children: [{// ⽤户管理,path: '/user',component: () => import('@/views/user/user.vue'),meta: {title: '用户管理',icon: 'user'}},{// 系统管理path: '/system',meta: {title: '系统管理',icon: 'system'},children: [{// 平台账号设置path: '/system/account',component: () =>import('@/views/system/Account/index.vue'),meta: {title: '平台账号设置',icon: 'tree'}},{// 字典设置path: '/system/dictionary',component: () =>import('@/views/system/Dictionary/index.vue'),meta: {title: '字典设置',icon: 'table'}},{// 参数设置path: '/system/parameter',component: () =>import('@/views/system/Parameter/index.vue'),meta: {title: '参数设置',icon: 'form'}},{// 字典详情页path: '/system/dictionaryDetail',component: () =>import('@/views/System/Dictionary/Detail.vue'),hidden: true}]}]},{// 401错误页path: '/401',component: () => import('@/views/error/401.vue')},{// 404错误页path: '/:pathMatch(.*)*',component: () => import('@/views/error/404.vue')}]
})
export default router

        这里使用了嵌套路由(children):外层是布局组件Layout,表示一级路由,内层是具体页面,表示二级路由。meta字段是自定义的数据容器,用来存放菜单需要的信息:

        title:显示菜单文字

        icon:显示图标名称(配合<svg-icon>使用)

        而属性hidden: true:控制是否在菜单中隐藏该路由(比如字典详情页不需要出现在菜单里,而是由字典设置页的数据点击后进入)

2 计算需要在菜单栏显示的路由

        在具体的菜单组件页:

<script setup>import { useRouter, useRoute } from 'vue-router'import { computed } from 'vue'// router 是路由实例const router = useRouter()// route 是当前显示/激活 的路由规则对象(代表的某个具体的路由规则)const route = useRoute()// 计算得到需要展示的 Layout 下的所有路由规则const showRoutes = computed(() => {// 筛选得到 Layout 路由规则const [layoutRoute] = router.options.routes.filter((route) => route.children)// 获取 Layout 路由的 childrenconst layoutChildren = layoutRoute.children// 过去掉 layoutChildren 下 hidden 为 true 的路由(hidden为true代表隐蔽)// 展示的路由结果const newChildren = []for (let i = 0, length = layoutChildren.length; i < length; i++) {const item = layoutChildren[i]// 如果没有隐藏属性if (!item.hidden) {// 如果配置了 children ,并且 children 里有路由规则if (item.children && item.children.length > 0) {const childrenList = []// 遍历内层 children,做同样的处理for (let j = 0, len = item.children.length; j < len; j++) {const child = item.children[j]if (!child.hidden) {childrenList.push(child)}}item.children = childrenList}// 添加值结果数组newChildren.push(item)}}// 返回展示的结果作为 showRoutes 的值(计算属性内部必须有返回值)return newChildren})console.log(`output->`, showRoutes.value)
</script>

        使用computed响应式地计算出要展示的菜单数据,筛选规则包括:

        (1)找到包含children的根布局路由(即/下的主结构)

        (2)过滤掉hidden: true的一级和二级菜单(如/System/Dictionary/Detail.vue不出现在菜单中)

        (3)返回干净的、可用于渲染的路由列表

        注意:为何用 computed?因为路由一旦改变或初始化完成,就需要立刻重新计算一次菜单内容,且结果依赖响应式数据(路由状态),所以computed是最佳选择。

3 菜单栏渲染

    <!-- 左侧菜单 --><el-menu :default-active="route.path" router><template v-for="item in showRoutes" :key="item.path"><!-- 有子菜单用 el-sub-menu 这套结构 --><el-sub-menu :index="item.path" v-if="item.children"><template #title><svg-icon :name="item.meta.icon" /><span class="title">{{ item.meta.title }}</span></template><el-menu-itemv-for="subItem in item.children":key="subItem.path":index="subItem.path"><svg-iconv-if="subItem.meta.icon":name="subItem.meta.icon":color="route.path === subItem.path ? '#0FA1FE' : ''"/><span class="title">{{ subItem.meta.title }}</span></el-menu-item></el-sub-menu><!-- 没有子菜单,直接用 el-menu-item 这套结构 --><el-menu-item :index="item.path" v-else><svg-icon:name="item.meta.icon":color="route.path === item.path ? '#0FA1FE' : ''"/><span class="title">{{ item.meta.title }}</span></el-menu-item></template></el-menu>

        在组件中,利用v-for遍历showRoutes(经过处理后的可见路由),根据是否有children自动判断是一级菜单还是可展开的二级菜单(v-if和v-else),使用Element Plus的<el-menu>组件构建标准菜单UI,:index="xxx"和router模式结合,实现点击跳转,:color实现当前路由对应菜单的高亮显示。

        最终效果如下所示:

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

相关文章:

  • 西安seo网站排名优化公司网站快速推广排名技巧
  • LeetCode算法日记 - Day 62: 黄金矿工、不同路径III
  • 济南建设工程信息网站asp.net实用网站开发
  • deepseek 的对话json导出成word和pdf
  • php 网站 项目如何用wordpress搭建个人博客
  • Prometheus监控K8S集群-ExternalName-endpoints-ElasticStack采集K8S集群日志实战
  • 解读DeepSeek-V3.2-Exp:基于MLA架构的Lightning Index如何重塑长上下文效率
  • 视频网站开发公司有哪些公司国家新闻出版
  • GitHub 热榜项目 - 日榜(2025-10-04)
  • datawhale RAG技术全栈指南 202509 第6次作业
  • 电影网站建设成本百怎么做网站
  • e语言可以做网站吗西安网站建设 翼驰
  • Redis 热点数据与冷数据解析
  • 【计算机视觉】车牌分割定位识别
  • wordpress做网站容易吗用lls建设一个网站
  • 从 3.6 亿订单表到毫秒级查询:分库分表指南
  • 网站怎样设计网页做黄金期货的网站
  • 无线网卡——WIFI7无法在Ubuntu22.04系统中使用
  • Ubuntu20.04下的Pytorch2.7.1安装
  • MySQL:C语言链接
  • 合肥市门户网站中国纪检监察报社长
  • 黑马点评秒杀优化和场景补充
  • 嵌入式硬件——基于IMX6ULL的UART(通用异步收发传输器)
  • Spark Shuffle:分布式计算的数据重分布艺术
  • 网站能看出建设时间吗网页设计工资统计
  • Postgres数据库truncate表无有效备份恢复---惜分飞
  • 【邪修玩法】如何在WPF中开放 RESTful API 服务
  • 开源 C++ QT QML 开发(二)工程结构
  • 2025生成式AI部署避坑指南:芯片卡脖子与依赖链爆炸的实战解决方案
  • 互联网新热土视角下开源AI大模型与S2B2C商城小程序的县域市场渗透策略研究