如果只有一级菜单只会显示一个按钮
<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-cascader
v-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-item
v-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>