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]
}
相关推荐
玖釉-3 分钟前
解决PowerShell执行策略导致的npm脚本无法运行问题
前端·npm·node.js
Larcher36 分钟前
新手也能学会,100行代码玩AI LOGO
前端·llm·html
徐子颐1 小时前
从 Vibe Coding 到 Agent Coding:Cursor 2.0 开启下一代 AI 开发范式
前端
小月鸭1 小时前
如何理解HTML语义化
前端·html
jump6801 小时前
url输入到网页展示会发生什么?
前端
诸葛韩信1 小时前
我们需要了解的Web Workers
前端
brzhang2 小时前
我觉得可以试试 TOON —— 一个为 LLM 而生的极致压缩数据格式
前端·后端·架构
yivifu2 小时前
JavaScript Selection API详解
java·前端·javascript
这儿有一堆花2 小时前
告别 Class 组件:拥抱 React Hooks 带来的函数式新范式
前端·javascript·react.js
十二春秋2 小时前
场景模拟:基础路由配置
前端