在开发中我们没有办法确定左侧的代码目录要是用多少层
如果写一个嵌套的话,就能无添加目录
目录结构
layout
components
Header
index.vue
Sidebar
index.vue
menuItem.vue
subMenu.vue
index.vue(下文的index.vue就是这个文件)
入口
type的类型
//路由的接口
export interface IRouterMap {
redirect?: string,
alwaysShow?: number,//当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式--如组件页面
hidden?: number,//当设置 true 的时候该路由不会再侧边栏出现 如401,login等页面,或者如一些编辑页面/edit/1
query: string,//访问路由的默认传递参数
name: string,//设定路由的名字,一定要填写不然使用<keep-alive>时会出现各种问题
path: string,//路由地址
meta?: IMeta,
component: string | object
children?: [IRouterMap],
}
//mate的接口
interface IMeta {
title?: string, // 设置该路由在侧边栏和面包屑中展示的名字
icon?: string,// 设置该路由的图标,对应路径src/assets/icons/svg
breadcrumb?: boolean,// 如果设置为false,则不会在breadcrumb面包屑中显示
noCache?: boolean,// 如果设置为true,则不会被 <keep-alive> 缓存(默认 false)
menuType: number,//类型(1目录 2菜单 3按钮 4数据 5字段)
}
index.vue文件
<template>
<el-radio-group v-model="isCollapse" style="position: absolute; top: 5px; z-index: 1; left: 10px; height: 50px">
<el-radio-button :label="false">展开</el-radio-button>
<el-radio-button :label="true">折叠</el-radio-button>
</el-radio-group>
<el-container class="layout-container-demo" style="height: 100%">
<el-aside :class="!isCollapse ? 'asideOpen' : 'asideClose'">
<Sidebar :isCollapse="isCollapse"></Sidebar>
</el-aside>
<el-container style="flex: 1">
<el-header style="text-align: right; font-size: 12px">
<Header></Header>
</el-header>
<el-main>
<router-view></router-view>
</el-main>
</el-container>
</el-container>
</template>
<script lang="ts" setup>
import { ref } from "vue";
import { Sidebar, Header } from "./components";
const isCollapse = ref(false);
</script>
<style scoped>
.asideOpen {
max-width: 200px;
}
.asideClose {
max-width: 80px;
}
</style>
./components文件夹
./components/index.ts文件
export { default as Sidebar } from './Sidebar/index.vue'
export { default as Header } from './Header/index.vue'
./components/Sidebar/index.vue文件
<template>
<el-scrollbar>
<div style="height: 50px"></div>
<el-menu :default-openeds="['0']" :collapse="isCollapse" class="el-menu-vertical-demo">
<sub-menu :data="sidebarRoutes" :index="0"></sub-menu>
</el-menu>
</el-scrollbar>
</template>
<script lang="ts" setup>
import subMenu from "./subMenu.vue";
import { Menu as IconMenu, Message, Setting } from "@element-plus/icons-vue";
import { computed, ref, watchEffect, defineProps } from "vue";
import { useRouterStore } from "@/stores";
import type { IRouterMap } from "@/router/index";
const routerStore = useRouterStore();
const props = defineProps({
isCollapse: Boolean,//是否折叠
});
const isCollapse = computed(() => props.isCollapse);
//左边的展示
const sidebarRoutes = computed<IRouterMap[]>(() => routerStore.sidebarRoutes);
// const isCollapse = ref(false);
</script>
<style lang="scss" scoped>
.el-menu {
border: 0;
}
.el-menu-vertical-demo:not(.el-menu--collapse) {
width: 200px;
// overflow: hidden;
min-height: 400px;
}
</style>
./components/Sidebar/subMenu.vue文件
<template>
<template v-for="(item, index) in sidebarRoutes" :key="index">
<el-sub-menu v-if="item.meta?.menuType == 1" :index="indexKey(parentIndex, index)">
<template #title>
<el-icon><IconMenu /></el-icon>
<!-- 需要放在一个标签没 要不然对折无隐藏标题 -->
<span>{{ item.meta?.title }}</span>
</template>
<sub-menu :data="item.children" :index="indexKey(parentIndex, index)"></sub-menu>
</el-sub-menu>
<template v-if="item.meta?.menuType == 2">
<menu-item :data="item" :index="indexKey(parentIndex, index)"></menu-item>
</template>
</template>
</template>
<script lang="ts" setup>
import menuItem from "./menuItem.vue";
import { defineProps, computed } from "vue";
import type { IRouterMap } from "@/router/index";
import { Menu as IconMenu } from "@element-plus/icons-vue";
const props = defineProps<{
data: IRouterMap[]; //具体的条目内容
index: number | string;
}>();
const parentIndex = computed(() => props.index);
const indexKey = function (parentIndex: number | string, index: number): string {
return `${parentIndex}-${index}`;
};
const sidebarRoutes = computed<IRouterMap[]>(() => props.data);
</script>
./components/Sidebar/menuItem.vue文件
<template>
<el-menu-item-group>
<el-menu-item :index="parentIndex" @click="goRouter(item)">
{{ item.meta?.title }}
</el-menu-item>
</el-menu-item-group>
</template>
<script lang="ts" setup>
import { defineProps, computed } from "vue";
import type { IRouterMap } from "@/router/index";
import { useRouter } from "vue-router";
import { Menu as IconMenu, Message, Setting } from "@element-plus/icons-vue";
const props = defineProps<{
data: IRouterMap; //具体的条目内容
index: number | string; //当前是第几个
}>();
//路由跳转
const router = useRouter();
//本节点的信息
const item = computed(() => props.data);
//当前的index
const parentIndex = computed(() => props.index);
//点击菜单 进行了跳转
function goRouter(item: IRouterMap) {
router.push({ path: item.path });
}
</script>