以下仅供参考,主要是用来自己保存知识点用的.
<!-- Menu.vue 菜单组件 -->
<template>
<ul class="menu-container" v-if="hasPermission">
<li v-for="item in menuData" :key="item.id" class="menu-item">
<!-- 菜单项内容 -->
<div
class="menu-label"
:class="{ 'has-children': item.children && item.children.length }"
@click="toggleChildren(item)"
>
<span class="menu-icon" v-if="item.icon">
<i :class="item.icon"></i>
</span>
<span class="menu-text">{{ item.name }}</span>
<span
class="menu-arrow"
v-if="item.children && item.children.length"
:class="{ 'expanded': item.expanded }"
>
<i class="arrow-icon"></i>
</span>
</div>
<!-- 递归子菜单 -->
<transition name="slide">
<recursive-menu
v-if="item.children && item.children.length && item.expanded"
:menu-data="item.children"
:permissions="permissions"
class="sub-menu"
/>
</transition>
</li>
</ul>
</template>
<script>
import { defineComponent, computed } from 'vue';
export default defineComponent({
name: 'RecursiveMenu',
props: {
menuData: {
type: Array,
required: true,
default: () => []
},
permissions: {
type: Array,
default: () => []
}
},
setup(props) {
// 检查当前菜单是否有权限显示
const hasPermission = computed(() => {
return props.menuData.some(item => {
return !item.permission || props.permissions.includes(item.permission);
});
});
// 切换子菜单展开状态
const toggleChildren = (item) => {
if (item.children && item.children.length) {
item.expanded = !item.expanded;
} else if (item.path) {
// 这里可以添加路由跳转逻辑
console.log('Navigate to:', item.path);
}
};
return {
hasPermission,
toggleChildren
};
}
});
</script>
<style scoped>
/* 基础样式 */
.menu-container {
list-style: none;
padding: 0;
margin: 0;
width: 100%;
}
.menu-item {
position: relative;
cursor: pointer;
}
.menu-label {
display: flex;
align-items: center;
padding: 12px 16px;
color: #333;
transition: all 0.3s ease;
border-radius: 4px;
}
.menu-label:hover {
background-color: #f5f5f5;
color: #1890ff;
}
.menu-icon {
margin-right: 8px;
font-size: 16px;
}
.menu-text {
flex: 1;
}
.menu-arrow {
transition: transform 0.3s ease;
}
.menu-arrow.expanded {
transform: rotate(90deg);
}
.arrow-icon {
display: inline-block;
width: 0;
height: 0;
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
border-left: 5px solid #666;
}
/* 子菜单样式 */
.sub-menu {
padding-left: 20px;
overflow: hidden;
}
/* 过渡动画 */
.slide-enter-active, .slide-leave-active {
transition: all 0.3s ease;
max-height: 500px;
}
.slide-enter-from, .slide-leave-to {
max-height: 0;
opacity: 0;
}
/* 权限控制样式 */
.no-permission {
display: none;
}
</style>
使用方法:
<template>
<div class="app-container">
<h1>无限递归菜单示例</h1>
<div class="menu-wrapper">
<recursive-menu :menu-data="menuData" :permissions="userPermissions" />
</div>
<div class="permission-control">
<h3>权限控制</h3>
<label v-for="perm in allPermissions" :key="perm">
<input type="checkbox" v-model="userPermissions" :value="perm" />
{{ perm }}
</label>
</div>
</div>
</template>
<script>
import { ref } from "vue";
import RecursiveMenu from "./components/RecursiveMenu.vue";
export default {
components: {
RecursiveMenu,
},
setup() {
// 所有可能的权限 可配合后端接口使用
const allPermissions = ref(["dashboard_view", "user_manage", "role_manage", "product_edit", "order_view", "report_view"]);
// 当前用户权限
const userPermissions = ref(["dashboard_view", "order_view"]);
// 菜单数据
const menuData = ref([
{
id: 1,
name: "仪表盘",
icon: "el-icon-monitor",
path: "/dashboard",
permission: "dashboard_view",
},
{
id: 2,
name: "用户管理",
icon: "el-icon-user",
expanded: false,
permission: "user_manage",
children: [
{
id: 21,
name: "用户列表",
path: "/user/list",
permission: "user_manage",
},
{
id: 22,
name: "用户组",
path: "/user/group",
permission: "user_manage",
},
],
},
{
id: 3,
name: "产品管理",
icon: "el-icon-goods",
expanded: false,
permission: "product_edit",
children: [
{
id: 31,
name: "产品列表",
path: "/product/list",
permission: "product_edit",
},
{
id: 32,
name: "分类管理",
path: "/product/category",
permission: "product_edit",
children: [
{
id: 321,
name: "一级分类",
path: "/product/category/level1",
},
{
id: 322,
name: "二级分类",
path: "/product/category/level2",
},
],
},
],
},
{
id: 4,
name: "订单管理",
icon: "el-icon-tickets",
expanded: false,
permission: "order_view",
children: [
{
id: 41,
name: "订单列表",
path: "/order/list",
},
{
id: 42,
name: "退货管理",
path: "/order/return",
},
],
},
{
id: 5,
name: "系统设置",
icon: "el-icon-setting",
children: [
{
id: 51,
name: "角色管理",
path: "/system/role",
permission: "role_manage",
},
{
id: 52,
name: "权限设置",
path: "/system/permission",
permission: "role_manage",
},
],
},
]);
return {
menuData,
allPermissions,
userPermissions,
};
},
};
</script>
<style>
.app-container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
font-family: Arial, sans-serif;
}
.menu-wrapper {
width: 300px;
border: 1px solid #eee;
border-radius: 4px;
padding: 10px;
margin-bottom: 20px;
}
.permission-control {
margin-top: 30px;
padding: 15px;
border: 1px solid #eee;
border-radius: 4px;
}
.permission-control label {
display: block;
margin: 8px 0;
cursor: pointer;
}
.permission-control input {
margin-right: 8px;
}
</style>