如果只有一级菜单只会显示一个按钮
<div style="width: 100%; margin-top: 10px; display: flex; align-items: center; border-bottom: 1px solid #ccc;"><template v-for="(menu, index) in cascaderData" :key="index"><el-cascaderv-if="menu.children && menu.children.length > 0"style="width: 120px;"v-model="selectedOptions[index]":options="menu.children"@change="handleCascaderChange(index, $event)":placeholder="menu.label"></el-cascader><el-button :style="{color: buttonColor}" plain @click="handleSelect(String(index))" v-else>{{ menu.label }}</el-button></template></div>
菜单结构说明:component对应的就是你要跳转的页面组件,也就是上面import进来的组件。然后通过emitComponentChange方法来跳转对应页面。
<script setup>
import {useRouter} from 'vue-router';
import signal from '@/views/drawing/station/index';
import permutation from '@/views/drawing/permutationtable/permutation';
import gdgtable from '@/views/drawing/permutationtable/gdgtable';
import request from "../../../utils/request";
import {watch} from "vue";import {useStationsStore} from "@/views/drawing/store/index";const stationsStore = useStationsStore();const router = useRouter();const buttonColor = ref('black')const drawCodeList = ref([]);const xhjMenu = ref([])const cascaderData =ref( [{value: '0',label: '基础数据',children: [],component: signal},{value: '1',label: '封面及目录',children: [{value: '1-1', label: '封面'},{value: '1-2', label: '目录'},]},{value: '2',label: '测试1',children: [{value: '2-1', label: '测试1-1'},{value: '2-2', label: '测试1-2'},]},{value: '4',label: '测试3',children: [{value: '4-1', label: '测试3-1', component: lsbtable},{value: '4-2', label: '测试3-2', component: dclsbtable},]},{value: '6',label: '测试4',children: [{value: '6-1', label: '测试4-1', children: xhjMenu.value}, //这里用到了动态请求后端获取的三级菜单{value: '6-2', label: '测试4-2', component: dctable},{value: '6-3', label: '测试4-3'},{value: '6-4', label: '测试4-4', children: [{value: '6-4-1', label: '测试4-4-1', component: qdcjtable},{value: '6-4-2', label: '测试4-4-2'},]},{value: '6-5', label: '测试4-5'},]},
]);// 用于存储选择的菜单项
const selectedOptions = ref([]);// 处理 el-cascader 改变事件
const handleCascaderChange = (index, value) => {recoverButton(index);let menu = String(value)if (value.length === 2) { //如果是二级菜单,截取第二位数据menu = String(value[1])}handleSelect(menu)
}//处理菜单跳转事件
const handleSelect = async (menu) => {buttonColor.value = '#a7aab1'let component = findComponentByValue(cascaderData.value, menu);if (menu === '0') {buttonColor.value = 'black';recoverButton(menu);}if (menu === '7-3') {const type = await changeStation();if (type === 4) {emitComponentChange(jkgksktable);} else {emitComponentChange(jkgTktable);}}if (menu.includes('xhjtable')){let tuzhiCode = findTuZhiCodeByValue(cascaderData.value, menu);stationsStore.setTuzhiCode(tuzhiCode);emitComponentChange(component);}if (component != null) {emitComponentChange(component);}
};//这个方法是用来跳转对应页面的
const emitComponentChange = (component) => {// 触发自定义事件,传递组件或其他数据const event = new CustomEvent('componentChange', {detail: component});window.dispatchEvent(event);
};//将其他按钮恢复原状
function recoverButton(index) {console.log(selectedOptions.value)for (const item of cascaderData.value) {selectedOptions.value[item.value] = []; //全部恢复原状// if (parseInt(item.value) !== index) {// selectedOptions.value[item.value] = [];//将除了当前选中的菜单框都恢复原状// }}console.log(selectedOptions.value)
}// 匹配菜单页面
function findComponentByValue(data, targetValue) {for (let i = 0; i < data.length; i++) {const item = data[i];if (item.value === targetValue) {return item.component;}if (item.children && item.children.length > 0) {const result = findComponentByValue(item.children, targetValue);if (result) {return result;}}}return null;
}// 获取图纸code
function findTuZhiCodeByValue(data, targetValue) {for (let i = 0; i < data.length; i++) {const item = data[i];if (item.value === targetValue) {return item.tuzhiCode;}if (item.children && item.children.length > 0) {const result = findTuZhiCodeByValue(item.children, targetValue);if (result) {return result;}}}return null;
}listDingXingTuList().then((data) => { //这里通过请求后端接口动态获取三级菜单并赋值drawCodeList.value = data.data;cascaderData.value[6].children[0].children = drawCodeList.value.map(item => ({value: 'xhjtable'+item.id, label: item.tuzhiName,component: xhjtable,tuzhiCode: item.tuzhiCode //格式和一二级菜单保持一致,可以增加字段}));
})</script>
下面是切换页面后要显示的目标页面,这里接收上面emitComponentChange 方法传递过来的组件
<template><el-row><el-col :span="20"><!-- 顶部菜单 --><div v-if="showTop"><topmenu /></div><!-- 右侧下方区域动态切换的内容 --><div style="flex: 1;"><component :is="currentComponent" /></div></el-col></el-row>
</template><script setup>
import {onMounted, shallowRef} from 'vue';
import Topmenu from "./station/topmenu";const currentComponent = shallowRef(signal);//主动监听事件
onMounted(() => {window.addEventListener('componentChange', (event) => {const component = event.detail;// 在这里处理接收到的组件或其他数据currentComponent.value = component;});
});getStationList()
</script>
还有一种方式是通过el-menu实现的,效果同上,使用的js方法都是一样的
<el-menu:default-active="activeIndex"class="el-menu-demo"mode="horizontal"@select="handleSelect"background-color="#f8f8f9"style="margin-top: 20px;margin-left: 1px"><template v-for="(item, index) in cascaderData"><template v-if="!item.children"><el-menu-item :key="item.index" :index="item.value">{{ item.label }}</el-menu-item></template><el-sub-menu v-else :key="item.value" :index="item.value"><template #title>{{ item.label }}</template><template v-for="(child, childIndex) in item.children"><template v-if="!child.children"><el-menu-item :key="child.value" :index="child.value">{{ child.label }}</el-menu-item></template><el-sub-menu v-else :key="child.value + '-sub'" :index="child.value"><template #title>{{ child.label }}</template><el-menu-itemv-for="(subItem, subIndex) in child.children":key="subItem.value":index="subItem.value">{{ subItem.label }}</el-menu-item></el-sub-menu></template></el-sub-menu></template></el-menu>