Vue自定义管理后台侧边栏SideBar

在做基于vue的PC管理后台项目的时候遇到了有UI要求的需求,这时候当然不能把element照搬到项目中,这个项目历时1个月,几乎是天天10点到3点回家…仅次写下留念

1.html结构

el-menu标签在这里唯一的作用就是充当侧边栏外面的边界…并对其默认样式进行了修改

<template>
    <el-menu
            :default-active="defaultActive"
            router
            :unique-opened="true">
        <div class="submenu-container" v-for="(item, index) in subRouter" :key="item">
            <div @click="handleGoSingleRouter(item, index)" :class="['prev-submenu', {'active-submenu': (item.path===currentPath)}]">{{item.meta.title}}</div>
            <el-collapse-transition>
                <div v-show="item.children && item.children.length > 0 && (item.showSub)" class="item-container">
                    <div @click="handleGoItemRouter(sub)" :class="['sub-item', {'item-select': (sub.path === currentSubPath)}]" v-for="sub in item.children" :key="sub">
                        <i :class="['heart-icon', {'blue-heart': sub.path === currentSubPath}]"></i>
                        <span class="sub-item-title">{{sub.meta.title}}</span>
                        <i v-show="sub.path === currentSubPath" class="arrow-right"></i>
                    </div>
                </div>
            </el-collapse-transition>
        </div>
    </el-menu>
</template>


<style lang="scss" scoped>
    .prev-submenu {
        font-size: 20px;
        color: #424E83;
        padding: 10px 0 10px 10%;
        &:hover {
            cursor: pointer;
            background-image: linear-gradient(270deg, #81C3F3 0%, #006CEB 100%);
        }
    }
    .active-submenu {
        background-image: linear-gradient(270deg, #81C3F3 0%, #006CEB 100%);
        color: #fff;
    }
    .item-container {
        padding: 8px 16px;
        width: 190px;
        .sub-item {
            display: flex;
            position: relative;
            font-size: 16px;
            padding: 12px 0;
            margin-bottom: 6px;
            &:hover {
                cursor: pointer;
                background: #DEEDFF;
                border-radius: 4px;
            }
            .heart-icon {
                margin-left: 10px;
                display: inline-block;
                width: 18px;
                height: 19px;
                background: url(//fe1.hdfimg.com/npublichealth/publichealth/images/gray_heart.png) no-repeat;
                background-size: 90% 90%;
            }
            .blue-heart {
                background: url(//fe1.hdfimg.com/npublichealth/publichealth/images/bule_heart.png) no-repeat;
                background-size: 90% 90%;
            }
            .sub-item-title {
                margin-left: 6px;
            }
            .arrow-right {
                position: absolute;
                right: 2px;
                top: 14px;
                display: inline-block;
                width: 18px;
                height: 18px;
                background: url(//fe1.hdfimg.com/npublichealth/publichealth/images/arrow_right.png) no-repeat;
                background-size: 60% 92%;
            }
        }
        .item-select {
            background: #DEEDFF;
            border-radius: 4px;
            color: #3F89EC;
        }
    }
</style>
<style>
    .el-menu {
        box-shadow: 8px 6px 6px 0 rgba(212,212,212,0.6);
    }
</style>

2.js逻辑

<script>
    import router from "../../../../router";
    import mixins from "../../../../mixins/index"
    // 监听历史记录点, 添加返回事件监听
    window.onpopstate = () => {
        window.location.reload();
    };
    export default {
        name: "index",
        components: {},
        mixins: [mixins],
        data () {
            return {
                subRouter: router.subRouter,
                currentPath: '', // 当前选中的一级路由
                currentSubPath: this.defaultActive, // 当前选中的2级路由
                showSub: false, // 是否展示子菜单
                sessionCurrentSubPath: window.sessionStorage.getItem('currentSubPath') || '',
            }
        },
        computed: {
            defaultActive () { // 默认激活index
                let pathArr = this.$route.path.split('/');
                return pathArr[pathArr.length -1 ]
            },
        },
        mounted () {
            this.currentPath = this.defaultActive;
            this.currentSubPath = sessionStorage.getItem('currentSubPath') || this.defaultActive;
            this.initShowSub();
            this.initActiveSubMenu();
        },
        methods: {
            /** 当前路由是否是某一个submenu的子路由,用于定位submenu
             * @param item {Array}
             * @return {boolean}
             */
            initSelectMenuFade (item) {
                let count = 0;
                const {path} = this.$route;
                let pathArr = path.split('/');
                if (item.children && item.children.length > 0) {
                    item.children.forEach(sub => {
                        if (sub.path === this.defaultActive || sub.path === sessionStorage.getItem('currentSubPath')) {
                            count ++;
                        }
                        if (pathArr.includes(sub.path)) {
                            count ++;
                            this.currentSubPath = sub.path;
                        }
                    })
                }
                return count > 0;
            },
            initActiveSubMenu () {
                this.subRouter.forEach(item => {
                    if (this.initSelectMenuFade(item)) {
                        this.currentPath = item.path
                    }
                })
            },
            // 对submenu的展开收起动画初始化
            initShowSub () {
                this.subRouter.forEach(item => {
                    item.showSub = this.initSelectMenuFade(item)
                })
            },
            // 点击过滤并更改showSub字段的值,用于控制sub的展开收起
            filterSubRouterShowSub () {
                return router.subRouter.map(item => {
                    // 点我自己
                    if (item.path === this.currentPath) {
                        item.showSub = !item.showSub
                    }
                    return item;
                });
            },
            // 只有单个路由
            handleGoSingleRouter (item) {
                this.currentPath = item.path;
                if (!item.children) {
                    this.clearShowSubStatus();
                    this.$router.push('/npublichealth/index/' + item.path)
                } else {
                    this.subRouter = this.filterSubRouterShowSub();
                }
            },

            // 多个路由中的单个路由跳转
            handleGoItemRouter (sub) {
                this.currentSubPath = sub.path;
                window.sessionStorage.setItem('currentSubPath', sub.path);
                this.$router.push('/npublichealth/index/' + sub.path)
            },
            // 清除所有showSub状态
            clearShowSubStatus () {
                this.currentSubPath = '';
                this.resetSubRouterShowSub();
            },
            resetSubRouterShowSub () {
                this.subRouter = this.subRouter.map(item => {
                    item.showSub = false;
                    return item;
                });
            }
        }
    }
</script>

mixin.js

import axios from '../utils/axios';
import {formatDate} from '../util';

export default {
    data () {
        return {
            page: 1, size: 10, total: 0, dataList: [], loading: false,
            fromType: this.getCurrentPath(1),
            pageSizes: [1, 5, 10, 20]
        }
    },
    methods: {
        async initList () {
            if (! await this.beforeInit()) {
                return
            }
            this.loading = true;
            axios({
                url: this.url,
                data: this.params,
                type: this.type,
                fullLoading: true
            }).then(res => {
                this.loading = false;
                res = JSON.parse(res)
                if (+res.errorCode === 0) {
                    const resData = res.data;
                    this.dataList = resData.data;
                    this.total = resData.pageInfo.total
                    this.$store.commit('SET_RESIDENTS', res.data.data)
                } else {
                    this.$message.error('请求失败,请稍后重试');
                }
            }).catch(err => {
                this.loading = false;
            })
        },
        async initMedicList () {
            if (! await this.beforeInit()) {
                return
            }
            axios({
                url: this.url,
                data: this.params,
                type: this.type,
                fullLoading: true
            }).then(res => {
                res = JSON.parse(res)
                if (+res.errorCode === 0) {
                    let resData = res.data;
                    resData.data = resData.data.map(item => {
                        item.createTime = formatDate(item.createTime);
                        return item;
                    });
                    this.dataList = resData.data;
                    this.total = resData.pageInfo.total;
                    this.$store.commit('SET_MEDIC_LIST', resData.data)
                }
            })
        },

        pageChange(e) {
            this.page = e;
            this.initList();
        },
        sizeChange(e) {
            this.initCurrentPage();
            this.size = e;
            this.initList();
        },
        medicPageChange (e) {
            this.page = e;
            this.initMedicList();
        },
        medicSizeChange (e) {
            this.initCurrentPage();
            this.size = e;
            this.initMedicList();
        },
        initCurrentPage () {
            this.page = 1;
        },
        getCurrentPath (index) {
            let pathArr = this.$route.path.split('/');
            return pathArr[pathArr.length -index ]
        },
        getCurrentIndexPath () {
            let pathArr = this.$route.path.split('/');
            pathArr.shift();
            return pathArr[2];
        },
        handleGoBackList () {
            this.$router.push(`/npublichealth/index/${this.getCurrentPath(2)}`)
        }
    }
}

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值