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 =[];
},
},
});
展示菜单效果: