框架修改思路

一、组件引入基本样式

面包屑(使用element plus的标签页)
复制代码
        <!-- 标签页区域 -->
        <el-tabs v-model="activeTab" type="card" closable @tab-remove="removeTab" class="top-tabs">
            <el-tab-pane 
                :key="tab.name" 
                :label="tab.title" 
                :name="tab.name" 
                v-for="tab in tabs"
            >
                <div class="tab-content-placeholder">
                    {{ tab.content }}
                </div>
            </el-tab-pane>
        </el-tabs>
菜单容器
复制代码
 <!-- 菜单容器 -->
        <div class="menu-wrapper">
            <!-- 折叠按钮区域 -->
            <div class="radio-group-container">
                <el-radio-group v-model="isCollapse" style="margin-bottom: 0;">
                    <div :class="['icon-background', { 'collapsed': isCollapse }]">
                        <el-icon :size="25" :color="isCollapse? 'white' : '#ffd04b'" @click="isCollapse =!isCollapse"
                            style="margin-top: 10px;margin-left: 10px;">
                            <component :is="isCollapse? Expand : Fold" />
                        </el-icon>
                    </div>
                </el-radio-group>
            </div>

            <!-- 主菜单区域 -->
            <el-menu 
                router 
                default-active="Login" 
                class="full-height-menu dark-menu" 
                @open="handleOpen"
                @close="handleClose" 
                :collapse="isCollapse" 
                background-color="#001529" 
                text-color="#bfcbd9"
                active-text-color="#409EFF" 
                style="margin-top: -10px;" 
                @select="handleMenuSelect"
            >
                <template v-for="item in dynamicMenuItems" :key="item.path">
                    <template v-if="item.children && item.children.length > 0">
                        <el-sub-menu :index="item.path">
                            <template #title>
                                <el-icon>
                                    <component :is="item.meta.icon" v-if="item.meta.icon" />
                                </el-icon>
                                <span>{{ item.meta.title }}</span>
                            </template>
                            <template v-for="child in item.children" :key="child.path">
                                <el-menu-item :index="child.path">
                                    <el-icon>
                                        <component :is="child.meta.icon" v-if="child.meta.icon" />
                                    </el-icon>
                                    <span>{{ child.meta.title }}</span>
                                </el-menu-item>
                            </template>
                        </el-sub-menu>
                    </template>
                    <el-menu-item v-else :index="item.path">
                        <el-icon>
                            <component :is="item.meta.icon" v-if="item.meta.icon" />
                        </el-icon>
                        <span>{{ item.meta.title }}</span>
                    </el-menu-item>
                </template>
            </el-menu>
        </div>

二.实现思路

1.导入必要的模块和组件
复制代码
import { ref, onMounted } from 'vue';
import { useRouter } from 'vue-router';
import {
    ElRadioGroup,
    ElMenu,
    ElMenuItem,
    ElIcon,
    ElSubMenu,
    ElTabs,
    ElTabPane
} from 'element-plus';
import {
    Expand,
    Fold
} from '@element-plus/icons-vue';

2. 定义响应式数据

复制代码
const router = useRouter();
const isCollapse = ref(true);
const dynamicMenuItems = ref([]);
const activeTab = ref('');
const tabs = ref([]);

3. 获取本地存储的菜单数据

复制代码
const getDynamicMenuItems = () => {
    const storedMenuPath = sessionStorage.getItem('menuPath');
    if (storedMenuPath) {
        const menuPathData = JSON.parse(storedMenuPath);
        dynamicMenuItems.value = menuPathData.map(item => {
            const menuItem = {
                path: item.path,
                meta: {
                    title: item.name,
                    icon: null
                }
            };
            if (item.children && item.children.length > 0) {
                menuItem.children = item.children.map(child => ({
                    path: child.path,
                    meta: {
                        title: child.name,
                        icon: null
                    }
                }));
            }
            return menuItem;
        });
    }
};

4. 查找菜单项及其所有子项的完整路径

复制代码
const findAllMenuPaths = (items) => {
    const paths = [];
    items.forEach(item => {
        paths.push(item.path);
        if (item.children) {
            paths.push(...findAllMenuPaths(item.children));
        }
    });
    return paths;
};

5. 菜单点击事件处理

复制代码
const handleMenuSelect = (key) => {
    const allPaths = findAllMenuPaths(dynamicMenuItems.value);
    if (!allPaths.includes(key)) return;

    const existingTab = tabs.value.find(tab => tab.name === key);
    const menuItem = findMenuItemByPath(key);
    
    if (menuItem) {
        if (existingTab) {
            activeTab.value = key;
        } else {
            const newTab = {
                name: key,
                title: menuItem.meta.title,
                content: `${menuItem.meta.title} 内容区域`
            };
            tabs.value.push(newTab);
            activeTab.value = key;
        }
        
        // 导航到对应路由
        router.push(key);
    }
};

6. 根据路径查找菜单项

复制代码
const findMenuItemByPath = (path, items = dynamicMenuItems.value) => {
    for (const item of items) {
        if (item.path === path) return item;
        if (item.children) {
            const found = findMenuItemByPath(path, item.children);
            if (found) return found;
        }
    }
    return null;
};

7. 处理标签页关闭事件

复制代码
const removeTab = (targetName) => {
    tabs.value = tabs.value.filter(tab => tab.name !== targetName);
    if (activeTab.value === targetName) {
        activeTab.value = tabs.value.length > 0 ? tabs.value[0].name : '';
    }
};

8. 处理菜单展开和关闭事件

复制代码
const handleOpen = (key, keyPath) => {
    console.log('菜单展开:', key, keyPath);
};

const handleClose = (key, keyPath) => {
    console.log('菜单关闭:', key, keyPath);
};

9. 组件挂载后执行的操作

复制代码
onMounted(() => {
    getDynamicMenuItems();
});
  • onMounted 是一个生命周期钩子函数,在组件挂载后执行。
  • 调用 getDynamicMenuItems 函数,从会话存储中获取菜单数据。

综上所述,这段代码实现了从会话存储中获取菜单数据,根据菜单点击动态创建和切换标签页,以及路由导航的功能

相关推荐
尾善爱看海4 小时前
Vue 面试收官篇:SSR、性能优化落地、30 道高频面试题精讲(附标准答案)
前端·javascript·vue.js·面试·vue
weixin_BYSJ19874 小时前
【计算机毕设】基于SpringBoot与Vue的文物保护档案管理系统08621
vue.js·spring boot·spring cloud·微服务·架构·django·课程设计
Bs_MoneyMagnet4 小时前
基于springboot+vue的个人健康管理系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·vue3·springboot3·计算机毕业设计
驳是4 小时前
一个组件,提升 react-router 开发的幸福感
前端·preact
GreenTea4 小时前
OpenAI Agents API 上手实测:一次调用把整个 agent loop 甩给 OpenAI
前端·后端·算法
星云API技术支持4 小时前
企业微信二次开发:群权限设置、成员管理与群资料维护的接口组合实践
java·前端·企业微信
京东云开发者5 小时前
81.8 秒的视频,我们改了 15 个版本:一次纯 Codex 驱动的 AI-native 视频实践
前端·aigc
Csvn5 小时前
TypeScript 大型项目架构:从单体 tsconfig 到分层可扩展的工程
前端
Bs_MoneyMagnet7 小时前
基于springboot+vue的心理咨询预约与随访平台的设计与实现 源码+文档
vue.js·spring boot·后端·spring·毕业设计·旅游·计算机毕业设计
计算机魔术师7 小时前
Dario Amodei 发文呼吁为前沿 AI 降速并提出三点计划
前端