在做一些管理后台的时候;一般会有权限不同看到的菜单也不同。而且菜单结构也是不确定有多少级别,或者无限级别。这里就需要组件递归渲染了
效果图:
后端菜单接口返回如下面这样的:
mm: [ { path:'hh', name:'系统管理', func_fid: 0, id: 1, children: [ { id: 1, func_fid: 1, path:'son1', name: '系统管理儿子', }, { id: 2, func_fid: 1, path:'hhh', name: '系统管理-角色', children: [ { id: 2, func_fid: 1, path: 'son1-1-1', name: '角色管理', children:[ { id: 2, func_fid: 2, path: 'son1-1-1', name: '角色管理儿子', children:[ { id: 2, func_fid: 2, path: 'son1-1-1', name: '角色管理儿子-----孙子', } ] } ] } ] }, { id: 12, path: 'son1-2', name: '用户管理' } ] }, { path:'ss', name:'教学管理', id: 2, func_fid: 0, children: [ { path:'son2', name:'教学管理儿子', id: 2, func_fid: 2, } ] }, { path:'zz', name:'行政管理', id: 3, func_fid: 0, children: [ { path:'son3', name:'行政管理儿子', id: 3, func_fid: 3, } ] }, ]
左侧菜单部分代码home.vue:
<template> <el-container> <el-aside width="collapse ? 200px : 70px"> <el-button color="#626aef" @click="collapseToggle()"> <el-icon> <Expand v-if="collapse" /> <Fold v-else /> </el-icon> </el-button> <el-menu :collapse="collapse" default-active="2" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose" active-text-color="#ffd04b" text-color="#fff" background-color="transparent" router @select="gg" > <left :dataToSon="store.mm" /> </el-menu> </el-aside> <el-container> <el-header height="80px"> <h1>大可的管理系统 - v1.0</h1> <div> <img src="@/assets/111.jpg" alt=""> <span></span> <el-button type="primary" @click="LogOut">退出登录</el-button> </div> </el-header> <el-main> <tab></tab> </el-main> <el-footer height="50px"> <p>© 版权所有: 大可</p> </el-footer> </el-container> </el-container> </template> <script setup lang="ts"> import { ref } from 'vue'; import { useRouter } from "vue-router"; import left from "./left.vue"; import tab from './tab.vue'; import { ElMessage, ElMessageBox} from "element-plus"; import { useAuthStore } from '@/store' const store = useAuthStore(); const collapse = ref<boolean>(false) const router = useRouter(); const collapseToggle = () => { collapse.value = !collapse.value } const ggvv = ref([1,2,3]) const handleOpen = () => { console.log('展开') } const gg = (e) => { console.log(e) } const handleClose = () => { console.log('收起') } const LogOut = () => { ElMessageBox.confirm( '确定要退出登录?', 'Warning', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning', } ) .then(() => { router.replace('/login') ElMessage({ type: 'success', message: '退出成功', }) }) .catch(() => { ElMessage({ type: 'info', message: '您取消了退出', }) }) } </script> <style scoped> .el-header { background: url("@/assets/111.jpg"); background-color: #f3d19e; display: flex; align-items: center; justify-content: space-between; } .el-header h1 { font-size: 26px; color: #fff; letter-spacing: 10px; } .el-header div { margin-right: 30px; } .el-header img { width: 40px; border-radius: 40px; vertical-align: middle; margin-right: 10px; } .el-header span { font-size: 18px; color: #fff; margin-right: 10px; } .el-header el-button { margin-left: 10px; } .el-aside { height: 100vh; background: url('@/assets/111.jpg'); transition: width 0.3s; text-align: right; } .el-aside .el-button { margin: 20px 10px 20px 0; } .el-aside .el-menu { border-right: none; } .el-footer { background-color: #EBEEF5; display: flex; align-items: center; } .el-footer p { font-size: 12px; color: #666; } </style>
菜单left: 组件
<script setup lang="ts"> import { ref, defineProps } from 'vue'; import { useAuthStore } from '@/store'; type HeaderProps = { dataToSon: number[]; }; // 2. type 声明的HeaderProps 用 defineProps注册 const zz = defineProps<HeaderProps>(); const hhkk = zz.dataToSon; console.log('-------------------') console.log(hhkk) console.log('-------------------') const list = ref<Array<object>>([]); const store = useAuthStore(); const gg = () => { console.log('ss') } </script> <template> <template v-for="(item, index) in hhkk" :key="item.id"> <!-- 非叶子节点 --> <el-sub-menu v-if="item.children" :index="item.id"> <template #title> <el-icon> <Setting /> </el-icon> <span v-text="item.name"></span> </template> <left :dataToSon="item.children"/> </el-sub-menu> <!-- 叶子节点(功能节点) --> <el-menu-item v-else :index="item.path"> <el-icon> <Menu /> </el-icon> <span v-text="item.name"></span> </el-menu-item> </template> </template> <style scoped lang="stylus"> </style>
至此左侧菜单就可以了