Element plus使用menu时候如何在折叠时候隐藏掉组件自带的小箭头

记录一下工作中使用element plus时候遇到的一个小bug

就是这个小箭头太折磨人了,因为我需要根据路由动态加载menu,所以对这个menu组件进行了一些处理,然后可能是因为破坏了它原来的层级关系吧导致折叠菜单的时候这个小箭头还在(官网的这个是会隐藏掉的)

后来我看了一下它的css,大概就是折叠的时候会在menu上加一个类类名为.el-menu--collapse然后可以根据这个类名进行item的名字隐藏

<style scoped lang="scss">
.menu-title {
  font-size: 14px;
}

.el-menu--collapse .el-sub-menu__title span {
  display: none;
}

.el-menu--collapse .el-menu-item span {
  display: none;
}
</style>

这样也就隐藏了文本但是这个小箭头很顽固不能隐藏,于是我尝试在用一个不带scoped的style就把这个箭头隐藏了

<style scoped lang="scss">
.menu-title {
  font-size: 14px;
}

.el-menu--collapse .el-sub-menu__title span {
  display: none;
}

.el-menu--collapse .el-menu-item span {
  display: none;
}
</style>
<style>
.el-menu--collapse .el-sub-menu .el-sub-menu__title .el-sub-menu__icon-arrow {
  display: none;
}
</style>

到这里bug就解决了,这个细节虽然小但是很不雅观

根据路由动态渲染menu

讲到了动态渲染menu顺带记录一下吧

思想很简单就是根据路由去递归嘛然后由于菜单分为目录菜单el-sub-menu和功能菜单el-menu-item,这里目录菜单呢就是点击展开然后它的里面又可能包含了多个功能菜单

这里就有思路了,根据路由来看没有children的就是功能菜单,有children且长度不为0的就是目录菜单然后目录菜单下可能也有目录菜单显然就需要递归一下。

//MenuComponent.vue 这个就是整个menu
<template>
  <el-menu
    :default-active="activeIndex"
    class="el-menu-vertical-demo"
    :collapse="isCollapse"
    background-color="#545c64"
    text-color="#fff"
    active-text-color="#ffd04b"
    router
  >
    <div class="scroll-container">
      <template v-for="item in filteredRoutes" :key="item.path">
        <MenuItem :item="item" :isCollapse="props.isCollapse" />
      </template>
    </div>
  </el-menu>
</template>

<script setup lang="ts">
import { ref, defineProps, defineComponent, computed } from 'vue'
import MenuItem from './MenuItem.vue'

const props = defineProps({
  routes: Array,
  activeIndex: String,
  isCollapse: Boolean
})
const filteredRoutes = computed(() => {
  if (props.routes?.length) {
    return props.routes.filter((route: any) => {
      if (route.meta && route.meta.show === false) {
        return false
      }
      if (route.children) {
        route.children = route.children.filter((child: any) => {
          return !(child.meta && child.meta.show === false)
        })
      }
      return true
    })
  } else {
    return []
  }
})

console.log(filteredRoutes.value)
</script>

<style scoped>
.el-menu-vertical-demo:not(.el-menu--collapse) {
  width: 200px;
  min-height: 400px;
}

.menu-title {
  font-size: 14px;
}

.scroll-container {
  max-height: calc(100vh - 60px); /* 调整这里的值以适应你的布局 */
  overflow-y: auto;
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* IE and Edge */
}

/* WebKit browsers (Safari, Chrome) */
.scroll-container::-webkit-scrollbar {
  display: none; /* 隐藏滚动条 */
}


</style>

//MenuItem.vue 这个就是相应的菜单项,由于有el-sub-menu和el-menu-item两种我们这里进行了一个判断并且在组件中进行了一个递归,这样不管是几级的目录我们都可以动态渲染,具有一定可扩展性
<template>
  <el-sub-menu
    v-if="item.children && item.children.length > 0"
    :index="item.path"
    :popper-append-to-body="false"
  >
    <template #title>
      <el-icon v-if="item.meta?.icon">
        <component :is="item.meta.icon" />
      </el-icon>
      <span class="menu-title">{{ item.meta?.title }}</span>
    </template>
    <template v-for="child in item.children" :key="child.path">
      <MenuItem :item="child" :is-collapse="isCollapse" />
    </template>
  </el-sub-menu>
  <el-menu-item v-else :index="item.path">
    <el-icon v-if="item.meta?.icon">
      <component :is="item.meta.icon" />
    </el-icon>
    <template #title>
      <span class="menu-title">{{ item.meta?.title }}</span>
    </template>
  </el-menu-item>
</template>

<script setup lang="ts">
import { defineProps, watch } from 'vue'

const props = defineProps({
  item: {
    type: Object,
    required: true
  },
  isCollapse: {
    type: Boolean,
    default: false
  }
})
</script>

<style scoped lang="scss">
.menu-title {
  font-size: 14px;
}

.el-menu--collapse .el-sub-menu__title span {
  display: none;
}

.el-menu--collapse .el-menu-item span {
  display: none;
}
</style>
<style>
.el-menu--collapse .el-sub-menu .el-sub-menu__title .el-sub-menu__icon-arrow {
  display: none;
}
</style>

然后就是使用这个组件了一般是在总布局的侧边栏

      <MenuComponent
        :routes="routes" // routes 是路由列表可以直接导入自己写的路由列表
        :activeIndex="activeIndex" //这个是记录当前选中的index
        :isCollapse="isCollapse" //这里传递是否折叠
      />

//注意在使用这个组件的布局页面要监听一下activeIndex的变化
// 使用 watch 监听路由变化
watch(
  () => route.path,
  newPath => {
    activeIndex.value = newPath
  },
  { immediate: true } // 初始化时立即同步一次
)


//路由中每一项加入meta
meta: {
    title: '短信记录',
    icon: getIconComponent('Document'), //获取element plus中的图标getIconComponent这个是我自定义的方法
    show: true //是否显示在菜单中
     }



//getIconComponent导入icon的方法如下

import * as Icons from '@element-plus/icons-vue'
import type { Component } from 'vue'

const iconMap: Record<string, Component> = Icons

export function getIconComponent(iconName: string): Component | undefined {
  return iconMap[iconName]
}
相关推荐
小丁爱养花4 分钟前
前端三剑客(三):JavaScript
开发语言·前端·javascript
ZwaterZ13 分钟前
vue el-table表格点击某行触发事件&&操作栏点击和row-click冲突问题
前端·vue.js·elementui·c#·vue
码农六六13 分钟前
vue3封装Element Plus table表格组件
javascript·vue.js·elementui
西凉河的葛三叔17 分钟前
vue3+elementui-plus el-dialog全局配置点击空白处不关闭弹窗
前端·vue3·elementui-plus
徐同保17 分钟前
el-table 多选改成单选
javascript·vue.js·elementui
快乐小土豆~~17 分钟前
el-input绑定点击回车事件意外触发页面刷新
javascript·vue.js·elementui
周三有雨24 分钟前
【面试题系列Vue07】Vuex是什么?使用Vuex的好处有哪些?
前端·vue.js·面试·typescript
木古古1837 分钟前
使用chrome 访问虚拟机Apache2 的默认页面,出现了ERR_ADDRESS_UNREACHABLE这个鸟问题
前端·chrome·apache
爱米的前端小笔记1 小时前
前端八股自学笔记分享—页面布局(二)
前端·笔记·学习·面试·求职招聘