<template>
<div class="menu_component">
<div v-for="(m,i) in menus" :key="i">
<div class="p_menu">
<div
:class="{single_menu: true, menu_hover: true}"
:id="`menuItem_${m.id}`"
:style="{ paddingLeft: paddingLeft(m) }"
@click="menuClick($event, m)"
>
<div class="menu_label_icon">
<Document class="menu_icon" />
<span>{{m.name}}</span>
</div>
<ArrowDownBold class="arrow_icon" v-if="m.children && m.children.length"></ArrowDownBold>
</div>
</div>
<div :class="{father_container: true}" :id="`fatherContainer_${m.id}`" v-if="m.children && m.children.length">
<MenuCpmponent
:menus="m.children"
/>
</div>
</div>
</div>
</template>
<script>
import {ArrowDownBold, ArrowUpBold, Document} from '@element-plus/icons-vue';
import {useStore} from 'vuex';
import { ElMessage } from 'element-plus/lib/components';
import {useRouter, useRoute} from 'vue-router';
export default {
name: 'MenuCpmponent',
components: {
ArrowDownBold,
ArrowUpBold,
Document
},
props: {
menus: {
type: Array,
default: () => {return []}
}
},
setup(props, context) {
const store = useStore();
const router = useRouter();
const routeObj = useRoute();
function menuClick(e, m) {
let currentTarget = e.currentTarget;
if (m.children && m.children.length) {
let targetContainer = document.getElementById('fatherContainer_' + m.id);
let existClassName = targetContainer.className;
if (existClassName.indexOf('father_container_expand') != -1) {
targetContainer.classList.remove('father_container_expand');
currentTarget.classList.remove('menu_expand');
let tempObj = {id: m.id, parentId: m.parentId};
store.commit('removeMenuClickMap', tempObj);
}else {
targetContainer.classList.add('father_container_expand');
currentTarget.classList.add('menu_expand');
let tempObj = {id: m.id, parentId: m.parentId};
store.commit('addMenuClickMap', tempObj);
}
}else {
// 跳转路由
// debugger
if (!m.path) {
ElMessage.warning('应用功能开发中...');
return;
};
if (m.path == routeObj.path) {
return;
}
let menuActive = document.querySelector('.menu_active');
if (menuActive) {
menuActive.classList.remove('menu_active');
};
let relateChunk = toLoopMenuRelate(m.parentId);
console.log('菜单关联关系', relateChunk);
let allExpandContainer = document.querySelectorAll('.father_container_expand');
allExpandContainer = Array.from(allExpandContainer);
allExpandContainer.forEach(m => {
m.classList.remove('father_container_expand');
});
let allExpandMenu = document.querySelectorAll('.menu_expand');
allExpandMenu = Array.from(allExpandMenu);
allExpandMenu.forEach(m => {
m.classList.remove('menu_expand');
});
relateChunk.forEach( c => {
let targetContainer = document.getElementById('fatherContainer_' + c);
targetContainer.classList.add('father_container_expand');
let menuItem = document.getElementById('menuItem_' + c);
menuItem.classList.add('menu_expand');
});
currentTarget.classList.add('menu_active');
// 释放已存的菜单展开项
store.commit('releaseMenuClickMap', relateChunk);
console.log('store.state.menuClickMap', store.state.menuClickMap);
router.push(m.path)
};
};
function toLoopMenuRelate(parentId) {
let menuClickMap = store.state.menuClickMap;
if (!menuClickMap[parentId] || (menuClickMap[parentId] && !menuClickMap[parentId].parentId)) {
return [parentId];
}else {
let relateChunk = toLoopMenuRelate(menuClickMap[parentId].parentId);
relateChunk.push(parentId)
return relateChunk;
}
};
function paddingLeft(m) {
let p = 10;
let add = (m.level > 3 ? 3 : m.level - 1) * 15;
return p + add + 'px';
};
return {
menuClick,
paddingLeft
}
},
}
</script>
<style lang="less">
.menu_component{
.menu_active{
background-color: rgba(64,158,254,0.20) !important;
}
.father_container{
overflow: hidden;
max-height: 0;
transition: all 0.2s;
}
.father_container_expand{
overflow: hidden;
max-height: 1000px;
transition: all 1s;
}
.menu_expand{
.arrow_icon{
transform: rotate(180deg);
}
}
}
</style>
<style lang="less">
.menu_component{
color: #666666;
font-size: 14px;
user-select: none;
overflow: hidden;
.p_menu{
width: 200px;
}
.single_menu{
width: 100%;
height: 45px;
display: flex;
align-items: center;
justify-content: space-between;
background-color: #FFF;
cursor: pointer;
}
.menu_label_icon{
display: flex;
align-items: center;
}
.menu_icon{
width: 16px;
margin-right: 5px;
}
.menu_hover:hover{
background-color: #f8f8f8;
}
.trees{
overflow: hidden;
height: 0;
transition: all 0.2s;
}
.trees_expand{
overflow: hidden;
height: auto;
transition: all 0.2s;
}
.arrow_icon{
width: 12px;
font-weight: 600;
margin-right: 10px;
}
}
</style>
addMenuClickMap(state, obj) {
state.menuClickMap[obj.id] = obj;
},
removeMenuClickMap(state, obj) {
let menuClickMap = state.menuClickMap;
delete menuClickMap[obj.id];
state.menuClickMap = menuClickMap;
},
releaseMenuClickMap(state, list=[]) {
let tempObj = {};
list.forEach(l => {
if (state.menuClickMap.hasOwnProperty(l)) {
tempObj[l] = state.menuClickMap[l];
}
});
state.menuClickMap = tempObj;
},
menuClickMap: {}
菜单手写vue
于 2022-11-22 00:14:31 首次发布