1.创建目录结构
进入cmd,先cd到项目目录(项目vue3-project)
cd vue3-project
mkdir -p src\\views\\home\\components\\menubar
2.创建组件文件
3.编辑menu-item-content.vue
<template><template v-if="item.icon"><lay-icon :type="item.icon"></lay-icon></template>{{ item.title }}
</template><script setup lang="ts">
import { computed } from 'vue';const props= defineProps({// 菜单内容content: null,
});// 获取父级菜单数据
const item = computed(() => {return props.content;
});</script>
<style scoped lang="scss"></style>
4.编辑menu-item.vue
<template><template v-if="item.children && item.children.length>0"><lay-sub-menu :id="item.path" ><template v-slot:title><MenuItemContent :content="item" /></template><o-menu v-for="data in item.children" :content="data" /></lay-sub-menu></template><template v-else><lay-menu-item :id="item.path" ><MenuItemContent :content="item" /></lay-menu-item></template>
</template><script setup lang="ts">
import { computed } from 'vue';
import MenuItemContent from './menu-item-content.vue';defineOptions({name:"OMenu"}
);
const props= defineProps({// 菜单内容content: null,
});// 获取父级菜单数据
const item = computed(() => {return props.content;
});</script>
<style scoped lang="scss"></style>
5. 编辑menubar.vue
<template><lay-menu v-model:selected-key="selectedKey"v-model:open-keys="openKeys":tree="true" :indent="true":collapse="collapse" @changeSelectedKey="changeSelectedKey"><template v-for="menu in menus"><MenuItem :content="menu" /></template></lay-menu>
</template><script setup lang="ts">
import { ref } from 'vue';
import { storeToRefs } from 'pinia';
import { useRouter, useRoute } from 'vue-router'
import { useMenuStore } from '@/stores/menu'
import MenuItem from './menu-item.vue';const menuStore = useMenuStore()
const { menus,collapse } = storeToRefs(menuStore)const route = useRoute();
const router = useRouter()const selectedKey = ref(route.path)
const openKeys = ref<string[]>([])const changePath=()=>{let len = route.matched.length;if(len>1){for(var i=len-2;i>0;i--){openKeys.value.push(route.matched[i].path);}}
}changePath();const changeSelectedKey=(val: string)=>{router.push(val);
}</script>
<style scoped lang="scss">.layui-nav{background-color:var(--o-sidebar-bg-color);
}.layui-nav-tree {width: var(--o-sidebar-width);
}:deep(.layui-nav-item>a *){color:var(--o-sidebar-text-color);
}:deep(.layui-nav-child){background-color:var(--o-sidebar-bg-color);
}:deep(.layui-nav-item>a){display:flex;}</style>
6.添加菜单数据类型定义
types/menu.d.ts
declare interface Meta{id: string;name: string;path: string;title: string;
}declare interface MenuMeta extends Meta{icon?: string;
}declare interface MenuJsonInfo extends MenuMeta{parentId: number;
}declare interface MenuInfo extends MenuMeta{children?: MenuInfo[];
}// 菜单信息
declare interface MenuInfoState {activeName: string;menu: MenuInfo;
}
7.添加store
stroes/menu.ts
import {defineStore} from 'pinia';/*** * @methods 设置菜单信息*/
export const useMenuStore = defineStore('menu',{persist: true,//数据持久化设置state: (): MenuInfoState => ({collapse: false,menu: {name: '',title: '',path: '/',children: []},}),getters:{menus(state){return state.menu.children;}},actions: {async gen(datas: MenuJsonInfo[]) {const that = this;const map:Record<number, MenuInfo> = {};datas.forEach((item: MenuJsonInfo) =>{map[item.id] = {title:item.title,name:item.name, path:item.path,icon:item.icon, children: [] };});const findParent = (item: MenuJsonInfo)=>{if(item.pid == 0 ){that.menu.children?.push(map[item.id]);}else {const parent = map[item.pid];if(parent){parent.children?.push(map[item.id]);}}};datas.forEach((item: MenuJsonInfo) =>{findParent(item);});},handleCollape(){this.collapse = !this.collapse;return this.collapse;},clear(){this.menu.children =[];},},});
展示菜单效果: