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]
}
相关推荐
摆烂工程师10 分钟前
ChatGPT免费用户可以使用Deep Research啦!并且o3、o4-mini的可使用次数翻倍!
前端·后端·程序员
狂炫一碗大米饭11 分钟前
作为前端你不得不知道的浏览器相关知识1🚀
前端
天天扭码19 分钟前
🔥 别再用 class 了!JS 原型链才是 YYDS
前端·javascript·面试
GISer_Jinger24 分钟前
📢《告别手动抓狂!Trae国际版+BrowserTools MCP 实现前端错误调试自动化》🚀
前端
前端大白话25 分钟前
震惊!90%前端工程师都踩过的坑!computed属性vs methods到底该怎么选?一文揭秘高效开发密码
前端·vue.js·设计模式
一天睡25小时25 分钟前
React与Vue表单的对比差异
前端·javascript
作曲家种太阳25 分钟前
第七章 响应式的 watch 实现【手摸手带你实现一个vue3】
前端
在澳门喝茶的芦竹27 分钟前
React高阶组件——React.momo
javascript·react.js
前端小巷子27 分钟前
深入解析 iframe
前端
WEI_Gaot27 分钟前
ES6 模板字符串
前端·javascript