一. 效果图

底层使用el-menu菜单组件,项目中要求动态获取菜单树,并且层级不固定。所以就在el-menu组件基础上封装了一下。
在这里插入图片描述

二. 实现代码
  1. SideBar.vue 文件
<template>
  <el-aside width="200px" style="background-color: #F3F6F9">
    <el-menu
      :background-color="menuBgColor"
      text-color="#555D6D"
      active-text-color="#5DA1FF"
      :default-active="activePath"
      @select="selectMenu"
    >
      <menutree :data="menuList" :active="menuSelect" />
    </el-menu>
  </el-aside>
</template>

<script>
import Menutree from './MenuTree'
export default {
  components: { Menutree },
  props: {
    menuBgColor: {
      type: String,
      default: '#F3F6F9'
    }
  },
  data() {
    return {
      activePath: this.$route.name,
      menuSelect: '',
      menuList: [
        {
          path: 'merchantList',
          title: '商户中心',
          icon: '',
          children: [
            {
              path: 'merchantList',
              title: '权限管理',
              icon: ''
            },
            {
              path: 'realNamehome',
              title: '企业信息管理',
              icon: ''
            },
            {
              path: 'news',
              title: '消息中心',
              icon: '',
              children: [
                {
                  path: 'newsList',
                  title: '已读消息',
                  icon: ''
                },
                {
                  path: '/',
                  title: '未读消息',
                  icon: ''
                }
              ]
            }
          ]
        }
      ]
    }
  },
  updated() {
    this.$nextTick(() => {
      this.setActivePath(this.menuList, this.$route.name)
    })
  },
  methods: {
    setActivePath(links, path) {
      links.some((item, index) => {
        if (path === item.path) {
          this.activePath = item.path + ',' + item.permissionId
          return true
        }
        if (item.actives) {
          if (item.actives.indexOf(path) > -1) {
            this.activePath = item.path + ',' + item.permissionId
            return true
          }
        }
        if (item.children && item.children.length) {
          this.setActivePath(item.children, path)
        }
        return false
      })
    },
    selectMenu(item, indexPath) {
      this.menuSelect = item
      const arr = item.split(',')
      if (arr[0] !== 'undefined') {
        this.$router.push({ name: arr[0] })
      }
    }
  }
}
</script>

<style lang="scss">
.el-submenu {
  .is-active {
    border-right: 3px solid $main-color;
  }
  .el-menu-item {
    height: 40px !important;
    line-height: 40px !important;

    &:hover {
      background-color: #f3f6f9 !important;
    }
  }
  .el-submenu__title {
    &:hover {
      background-color: #f3f6f9 !important;
    }
    .el-submenu__icon-arrow {
      color: #b4b8c5;
    }
  }
}
.menuTree {
  .el-menu-item {
    height: 50px;
    line-height: 50px;
    box-sizing: border-box;
  }
  .el-submenu__title {
    height: 50px;
    line-height: 50px;
    box-sizing: border-box;
  }
}
</style>
  1. MenuTree.vue文件
<template>
  <div class="menuTree">
    <label v-for="item in data" :key="item.path">
      <el-submenu v-if="item.children && item.children.length>0" :index="item.title">
        <template slot="title">
          <svg-icon v-if="item.icon" :svg-name="getPath(item.icon)" class-name="menu-icon" />
          <span class="menu-text">{{ item.title }}</span>
        </template>
        <menutree :data="item.children" :active="active" />
      </el-submenu>
      <el-menu-item v-else :index="item.path+','+item.permissionId" :disabled="item.path?false:true">
        <span slot="title">
          <svg-icon v-if="item.icon" :svg-name="getPath(item.icon)" class-name="menu-icon" />
          <span class="menu-text">{{ item.title }}</span>
          <span v-if="(item.path+','+item.permissionId) === active" class="menu-bg" />
        </span>
      </el-menu-item>
    </label>
  </div>
</template>

<script>
export default {
  name: 'Menutree',
  props: {
    data: {
      type: Array,
      required: true
    },
    active: {
      type: String,
      default: ''
    }
  },
  methods: {
    getPath(path) {
      if (typeof path === 'undefined') {
        return
      }
      const index = path.indexOf('.')
      return path.substring(0, index)
    }
  }
}
</script>

<style lang="scss" scoped>
.menuTree {
  /deep/.el-menu-item {
    position: relative;

    &:hover {
      background-color: rgb(243, 246, 249) !important;
    }

    .menu-bg {
      position: absolute;
      display: block;
      width: 100%;
      height: 100%;
      background-color: #5da1ff;
      opacity: 0.1;
      left: 0;
      top: 0;
    }
  }
  .is-active > .el-submenu__title {
    color: #2b77ff;
  }
  .menu-icon {
    width: 16px;
    height: 16px;
  }
  .menu-text {
    margin-left: 8px;
  }
}
</style>

三. 菜单选中处理方式

刷新浏览器,菜单选中状态会丢失,这就要求我们做一下处理。根据页面地址来设置菜单选中状态。

 updated() {
    this.$nextTick(() => {
      this.setActivePath(this.menuList, this.$route.name)
    })
  }
methods:{
setActivePath(links, path) {
      links.some((item, index) => {
        if (path === item.path) {
          this.activePath = item.path + ',' + item.permissionId
          return true
        }
        if (item.actives) {
          if (item.actives.indexOf(path) > -1) {
            this.activePath = item.path + ',' + item.permissionId
            return true
          }
        }
        if (item.children && item.children.length) {
          this.setActivePath(item.children, path)
        }
        return false
      })
    }
 }
Logo

前往低代码交流专区

更多推荐