news 2026/9/6 9:40:16

Element Plus Menu组件,实现点击目录而不是叶子节点也可以跳转,且支持高亮状态更新

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Element Plus Menu组件,实现点击目录而不是叶子节点也可以跳转,且支持高亮状态更新
<template> <div class="m-nav-wrap"> <div class="m-nav"> <div class="m-logo"></div> <!-- 移动端:汉堡菜单按钮 --> <div v-if="isMobile" class="m-hamburger" @click="drawerVisible = true"> <span></span> <span></span> <span></span> </div> <!-- 桌面端:横向菜单 --> <el-menu v-if="!isMobile" :default-active="activeIndex" class="m-nav-menu" mode="horizontal" background-color="#001A33" text-color="#fff" active-text-color="#3489EB" @select="handleSelect" > <template v-for="menu in menuConfig" :key="menu.index"> <!-- 特殊按钮样式(联系我们) --> <div v-if="menu.isSpecialButton" class="m-special-button-wrapper"> <div class="m-contact-button" :class="{ 'is-active': activeIndex === menu.index }" @click="handleSelect(menu.index, [menu.index])" > {{ menu.label }} </div> </div> <!-- 一级菜单(无子菜单) --> <el-menu-item v-else-if="!menu.children" :index="menu.index"> {{ menu.label }} </el-menu-item> <!-- 一级菜单(有子菜单) --> <el-sub-menu v-else :index="menu.index" @click.native="handleSelectMenu(menu.index)"> <template #title>{{ menu.label }}</template> <!-- 二级菜单 --> <template v-for="child in menu.children" :key="child.index"> <!-- 二级菜单项(无子菜单) --> <el-menu-item v-if="!child.children" :index="child.index"> {{ child.label }} </el-menu-item> <!-- 二级菜单(有子菜单) --> <el-sub-menu v-else :index="child.index"> <template #title>{{ child.label }}</template> <el-menu-item v-for="grandChild in child.children" :key="grandChild.index" :index="grandChild.index" > {{ grandChild.label }} </el-menu-item> </el-sub-menu> </template> </el-sub-menu> </template> </el-menu> </div> <!-- 移动端:侧边抽屉菜单 --> <el-drawer v-model="drawerVisible" direction="ltr" :size="280" class="m-mobile-drawer" > <el-menu :default-active="activeIndex" class="m-mobile-menu" mode="vertical" background-color="#001A33" text-color="#fff" active-text-color="#3489EB" :router="true" @select="handleMobileSelect" > <template v-for="menu in menuConfig" :key="menu.index"> <!-- 一级菜单(无子菜单) --> <el-menu-item v-if="!menu.children" :index="menu.index"> {{ menu.label }} </el-menu-item> <!-- 一级菜单(有子菜单) --> <el-sub-menu v-else :index="menu.index" @click.native="handleSelectMenu(menu.index)"> <template #title>{{ menu.label }}</template> <!-- 二级菜单 --> <template v-for="child in menu.children" :key="child.index"> <!-- 二级菜单项(无子菜单) --> <el-menu-item v-if="!child.children" :index="child.index"> {{ child.label }} </el-menu-item> <!-- 二级菜单(有子菜单) --> <el-sub-menu v-else :index="child.index"> <template #title>{{ child.label }}</template> <el-menu-item v-for="grandChild in child.children" :key="grandChild.index" :index="grandChild.index" > {{ grandChild.label }} </el-menu-item> </el-sub-menu> </template> </el-sub-menu> </template> </el-menu> </el-drawer> </div> </template> <script lang="ts" setup> import { ref, onMounted, watch } from 'vue' import { useRouter, useRoute } from 'vue-router' import { menuConfig, setDocumentTitle } from './menu-config' import { useResponsive } from './use-responsive' const router = useRouter() const route = useRoute() const activeIndex = ref('/') const drawerVisible = ref(false) // 响应式检测 const { isMobile } = useResponsive() // 桌面端菜单选择 const handleSelect = (key: string, keyPath: string[]) => { console.log('Selected:', key, keyPath) // 更新激活状态 activeIndex.value = key // 设置页面标题 setDocumentTitle(key) // 路由跳转(仅当 index 是有效路径时) if (key.startsWith('/')) { router.push({ path: key }) } } // 移动端菜单选择 const handleMobileSelect = (key: string, keyPath: string[]) => { handleSelect(key, keyPath) // 关闭抽屉 drawerVisible.value = false } const handleSelectMenu = (path: any) => { console.log('path', path) // 更新激活状态 activeIndex.value = path // 设置页面标题 setDocumentTitle(path) // 路由跳转 router.push({ path }) } // 监听路由变化,同步更新激活状态 watch( () => route.path, (newPath) => { activeIndex.value = newPath setDocumentTitle(newPath) } ) onMounted(() => { // 初始化当前路由 const currentPath = router.currentRoute.value.path activeIndex.value = currentPath // 设置初始页面标题 setDocumentTitle(currentPath) }) </script> <style lang="css" scoped src="./index.css"></style>
// 菜单配置 export interface MenuItem { index: string label: string title?: string // 用于设置 document.title children?: MenuItem[] isSpecialButton?: boolean // 是否为特殊按钮样式 } export const menuConfig: MenuItem[] = [ { index: '/', label: '首页', }, { index: '/productCenter/index', label: '产品中心', children: [ { index: '/productCenter/index', label: '快速入口', }, { index: '/productCenter/aiAppOpPlat', label: 'AI应用运营平台', }, ], }, { index: '/successStories/index', label: '成功故事', title: '成功故事', children: [ { index: '/successStories/index', label: '快速入口', }, { index: '/successStories/edu', label: '教育', }, ], }, { index: '/partner', label: '合作伙伴', title: '合作伙伴', }, { index: '4', label: '关于我们', title: '关于我们', children: [ { index: '/about', label: '公司介绍', title: '公司介绍', }, ], }, { index: '6', label: '资讯中心', title: '资讯中心', children: [ { index: '/news', label: '最新资讯', title: '最新资讯', }, ], }, { index: '/contact', label: '联系我们', title: '联系我们', isSpecialButton: true, }, ] // 网站名称后缀 export const SITE_NAME = '通圆数智' // 根据 index 查找菜单标题 export function findMenuTitle( menuIndex: string, menus: MenuItem[] = menuConfig, ): string | null { for (const menu of menus) { if (menu.index === menuIndex) { return menu.title || menu.label } if (menu.children) { const title = findMenuTitle(menuIndex, menu.children) if (title) return title } } return null } // 设置页面标题 export function setDocumentTitle(menuIndex: string) { const title = findMenuTitle(menuIndex) if (title) { document.title = `${title} - ${SITE_NAME}` } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/3 1:32:42

【vtkPolyDataPointSampler 】——多边形数据点采样技术详解

VTK核心类解析:vtkPolyDataPointSampler 多边形数据点采样技术详解 简单说,vtkPolyDataPointSampler 就是 VTK里的 “点生成器”—— 专门给 3D 模型(比如三角形、多边形组成的物体)表面或内部,按需求打一堆采样点,生成的点云能直接用在后续的可视化、建模或计算里。 一…

作者头像 李华
网站建设 2026/9/3 7:59:35

电子签章选型指南:云巨头生态服务与垂直专业厂商的六大维度解析

随着电子签章应用在市场越来越普及和受追捧&#xff0c;超级大厂也相继推出了自己的电子签章产品&#xff0c;如华为的华为云电子签、阿里的阿里云电子签、腾讯的腾讯电子签服务。那这些大厂推出的电子签章产品和服务与传统第三方电子签公司北京安证通有什么相同和区别呢&#…

作者头像 李华
网站建设 2026/9/4 1:12:40

具身智能:行业成果与核心困难点全解析

具身智能作为 AI 与机器人融合的前沿领域&#xff0c;正从实验室走向产业应用&#xff0c;呈现出技术突破与落地挑战并存的发展态势。以下是当前行业成果与核心困难点的系统梳理。 一、行业成果&#xff1a;技术突破与场景落地加速 1. 核心技术突破 技术维度关键成果典型案例…

作者头像 李华
网站建设 2026/9/3 7:59:38

大模型微调全攻略:定制专属模型,简单得像打开浏览器

文章系统介绍大模型微调生态系统&#xff0c;详述多种开源(Qwen、DeepSeek等)和闭源(GPT、Claude等)模型特点及适用场景&#xff0c;对比全参数、LoRA/QLoRA等微调方法的算力需求与效果。重点推荐LLaMA-Factory Online平台&#xff0c;通过其可视化界面&#xff0c;开发者无需编…

作者头像 李华
网站建设 2026/9/3 7:59:42

⓫⁄₇ ⟦ OSCP ⬖ 研记 ⟧ Windows权限提升 ➱ 滥用Windows服务提权(上)

郑重声明&#xff1a;本文所涉安全技术仅限用于合法研究与学习目的&#xff0c;严禁任何形式的非法利用。因不当使用所导致的一切法律与经济责任&#xff0c;本人概不负责。任何形式的转载均须明确标注原文出处&#xff0c;且不得用于商业目的。 &#x1f50b; 点赞 | 能量注入…

作者头像 李华
网站建设 2026/9/3 1:12:15

博弈思维是可以学习的

博弈思维是可以学习的很多人提起博弈思维&#xff0c;总会下意识觉得它是“天生的智慧”——是那些善于算计、懂得权衡的人&#xff0c;与生俱来的能力&#xff0c;普通人难以企及。但事实上&#xff0c;博弈思维从来不是天赋的专属&#xff0c;它和读书、写字、思考一样&#…

作者头像 李华