源码 https://github.com/ohoherror/...

menuItem.js
外围:判断菜单还有没有children,有children就递归,没有就展现菜单名

<template>    <template v-for="item in arrList">        <el-menu-item v-if='!item.children' @click="toMenu(item)" :key="'/' + item.url" :index="'/' + item.url">            <span>{{ item.name }}</span>        </el-menu-item>        <el-sub-menu :index="item.menuId.toString()" v-else>            <template #title><span>{{ item.name }}</span></template>            <menu-item :arrList="item.children" @toMenu="toMenu"></menu-item>        </el-sub-menu>    </template></template><script  setup>import { pathArr } from '@/router/routes'import menuItem from './menuItem.vue'import { useRouter } from 'vue-router'import { useStore } from 'vuex';//vue3 props的获取const props = defineProps({    arrList: Array,});const router = useRouter()let store = useStore()const toMenu = (ele) => {    let checkedList = store.state.tabList    console.log(checkedList)    if (pathArr().includes('/' + ele.url)) {        let ids = checkedList.map(ele => ele.menuId)        //判断tabs是否存在该菜单        if (!ids.includes(ele.menuId)) {            checkedList.push(ele)        }        store.commit('setTabList', checkedList)        router.push({ path: '/' + ele.url })    } else {        ElMessage.error('暂无组件')    }}</script>

leftNav.js 左侧菜单总列表

<template>    <el-row class="">        <el-col>            <el-menu :collapse="isCollapse" class="el-menu-vertical-demo" :default-active="curPath" @open="handleOpen"                @close="handleClose">                <el-sub-menu v-for="item in menuList" :key="item.menuId" :index="item.menuId.toString()">                    <template #title>                        <span>{{ item.name }}</span>                    </template>                     <!-- 此处调用menu-item组件 -->                    <menu-item :arrList="item.children"></menu-item>                </el-sub-menu>            </el-menu>        </el-col>    </el-row></template><script  setup>import { reactive, ref, onMounted, watch } from 'vue'import navApi from '@/api/navApi'import { useRouter } from 'vue-router'import { useStore } from 'vuex';import { toRaw } from '@vue/reactivity'import { listMenu } from '../../../config/menu'import menuItem from './menuItem.vue'const router = useRouter()const menuList = ref([])let curPath = ref()const isCollapse = ref(false)onMounted(() => {    if (router.name !== 'login') {        getNav()    }})//路由监听watch(() => router.currentRoute.value.path, (newValue, oldValue) => {    curPath.value = newValue}, { immediate: true })const handleOpen = () => {}const handleClose = () => {}const getNav = () => {    menuList.value = listMenu}</script>

菜单列表测试数据menu.js

export const listMenu = [{    menuId: 1,    name: "系统管理",    open: null,    orderNum: 0,    parentId: 0,    parentName: null,    perms: null,    type: 0,    url: null,    children: [        {            icon: "role",            children: [                {                    icon: "role",                    children: [                        {                            icon: "role",                            children: null,                            menuId: 144,                            name: "测试治理",                            open: null,                            orderNum: 2,                            parentId: 44,                            parentName: null,                            perms: null,                            type: 1,                            url: "sys/test",                        }                    ],                    menuId: 44,                    name: "子系统治理",                    open: null,                    orderNum: 2,                    parentId: 3,                    parentName: null,                    perms: null,                    type: 1,                }            ],            menuId: 3,            name: "角色治理",            open: null,            orderNum: 2,            parentId: 1,            parentName: null,            perms: null,            type: 1,        },        {            icon: "menu",            children: null,            menuId: 4,            name: "菜单治理",            open: null,            orderNum: 3,            parentId: 1,            parentName: null,            perms: null,            type: 1,            url: "sys/menu",        }    ]}]