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]
}
相关推荐
桂月二二27 分钟前
探索前端开发中的 Web Vitals —— 提升用户体验的关键技术
前端·ux
CodeClimb1 小时前
【华为OD-E卷 - 第k个排列 100分(python、java、c++、js、c)】
java·javascript·c++·python·华为od
沈梦研1 小时前
【Vscode】Vscode不能执行vue脚本的原因及解决方法
ide·vue.js·vscode
hunter2062062 小时前
ubuntu向一个pc主机通过web发送数据,pc端通过工具直接查看收到的数据
linux·前端·ubuntu
qzhqbb2 小时前
web服务器 网站部署的架构
服务器·前端·架构
刻刻帝的海角2 小时前
CSS 颜色
前端·css
轻口味2 小时前
Vue.js 组件之间的通信模式
vue.js
浪浪山小白兔3 小时前
HTML5 新表单属性详解
前端·html·html5
lee5763 小时前
npm run dev 时直接打开Chrome浏览器
前端·chrome·npm
2401_897579653 小时前
AI赋能Flutter开发:ScriptEcho助你高效构建跨端应用
前端·人工智能·flutter