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]
}
相关推荐
sanx189 分钟前
一站式电竞平台解决方案:数据、直播、源码,助力业务飞速启航
前端·数据库·apache·数据库开发·时序数据库
余防16 分钟前
存储型XSS,反射型xss
前端·安全·web安全·网络安全·xss
ObjectX前端实验室30 分钟前
从零到一:系统化掌握大模型应用开发【目录】
前端·llm·agent
guoyp212637 分钟前
前端实验(二)模板语法
前端·vue.js
葡萄城技术团队43 分钟前
Excel 转在线协作难题破解:SpreadJS 纯前端表格控件的技术方案与实践
前端·excel
我的xiaodoujiao43 分钟前
Windows系统Web UI自动化测试学习系列3--浏览器驱动下载使用
前端·windows·测试工具·ui
一只小风华~1 小时前
学习笔记:Vue Router 中的嵌套路由详解[特殊字符]概述
前端·javascript·vue.js
泻水置平地1 小时前
若依前后端分离版实现前端国际化步骤
前端
Villiam_AY1 小时前
从后端到react框架
前端·react.js·前端框架
CodeCraft Studio1 小时前
全球知名的Java Web开发平台Vaadin上线慧都网
java·开发语言·前端·vaadin·java开发框架·java全栈开发·java ui 框架