菜单手写vue

<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: {}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值