• element收缩已经展开的菜单


     问题描述

    VUE菜单有一个BUG,当我们点击其它按钮或者首页的时候,已经展示的一级菜单是不会自动收缩的。这个问题也导致很多开发者把一级菜单都换成了二级菜单。

    错误展示

    错误的效果请看下图。

     解决方法

    1、寻找菜单文件

    因为我使用的是ruoyi的前端框架,所以菜单文件的路径是src/layout/components/Sidebar/index.vue文件,如果大家使用的是其他的框架或者自己写的去全局搜索关键字【el-menu】就能找到菜单页面。文件路径如下图

    2、添加以下代码

    1. // el-menu菜单中添加ref和open事件
    2. <el-menu ref="menu" @open="handleOpen">el-menu>
    3. data() {
    4. return {
    5. // 记录用户上次点击的菜单索引
    6. keyIndex:0,
    7. };
    8. },
    9. watch: {
    10. $route () {
    11. // 监控用户点击的菜单,如果是首页或者个人详情页面都要把上次打开的页面收缩起来。
    12. if (this.$route.path === '/index' ||this.$route.path === "/user/profile") {
    13. this.$refs.menu.close(this.keyIndex);
    14. }
    15. }
    16. },
    17. methods: {
    18. handleOpen (key) {
    19. this.keyIndex = key;
    20. }
    21. },

     3、完整的代码

    1. <template>
    2. <div :class="{'has-logo':showLogo}" :style="{ backgroundColor: settings.sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }">
    3. <logo v-if="showLogo" :collapse="isCollapse" />
    4. <el-scrollbar :class="settings.sideTheme" wrap-class="scrollbar-wrapper">
    5. <el-menu
    6. ref="menu"
    7. @open="handleOpen"
    8. :default-active="activeMenu"
    9. :collapse="isCollapse"
    10. :background-color="settings.sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground"
    11. :text-color="settings.sideTheme === 'theme-dark' ? variables.menuColor : variables.menuLightColor"
    12. :unique-opened="true"
    13. :active-text-color="settings.theme"
    14. :collapse-transition="false"
    15. mode="vertical"
    16. >
    17. <sidebar-item
    18. v-for="(route, index) in sidebarRouters"
    19. :key="route.path + index"
    20. :item="route"
    21. :base-path="route.path"
    22. />
    23. el-menu>
    24. el-scrollbar>
    25. div>
    26. template>
    27. <script>
    28. import { mapGetters, mapState } from "vuex";
    29. import Logo from "./Logo";
    30. import SidebarItem from "./SidebarItem";
    31. import variables from "@/assets/styles/variables.scss";
    32. export default {
    33. components: { SidebarItem, Logo },
    34. data() {
    35. return {
    36. keyIndex:0,
    37. };
    38. },
    39. watch: {
    40. $route () {
    41. if (this.$route.path === '/index' ||this.$route.path === "/user/profile") {
    42. this.$refs.menu.close(this.keyIndex);
    43. }
    44. }
    45. },
    46. methods: {
    47. handleOpen (key) {
    48. this.keyIndex = key;
    49. }
    50. },
    51. computed: {
    52. ...mapState(["settings"]),
    53. ...mapGetters(["sidebarRouters", "sidebar"]),
    54. activeMenu() {
    55. const route = this.$route;
    56. const { meta, path } = route;
    57. // if set path, the sidebar will highlight the path you set
    58. if (meta.activeMenu) {
    59. return meta.activeMenu;
    60. }
    61. return path;
    62. },
    63. showLogo() {
    64. return this.$store.state.settings.sidebarLogo;
    65. },
    66. variables() {
    67. return variables;
    68. },
    69. isCollapse() {
    70. return !this.sidebar.opened;
    71. }
    72. }
    73. };
    74. script>

    4、修改后的效果

    5、到此功能完成。


    -----华丽的分割线,以下是凑字数,大家不用花时间看,快去改代码-----

    -----华丽的分割线,以下是凑字数,大家不用花时间看,快去改代码-----

    -----华丽的分割线,以下是凑字数,大家不用花时间看,快去改代码-----

    1. <template>
    2. <div v-if="!item.hidden">
    3. <template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
    4. <app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path, onlyOneChild.query)">
    5. <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
    6. <item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="$t(onlyOneChild.meta.title)" />
    7. el-menu-item>
    8. app-link>
    9. template>
    10. <el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
    11. <template slot="title">
    12. <item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" />
    13. template>
    14. <sidebar-item
    15. v-for="child in item.children"
    16. :key="child.path"
    17. :is-nest="true"
    18. :item="child"
    19. :base-path="resolvePath(child.path)"
    20. class="nest-menu"
    21. />
    22. el-submenu>
    23. div>
    24. template>
    25. <script>
    26. import path from 'path'
    27. import { isExternal } from '@/utils/validate'
    28. import Item from './Item'
    29. import AppLink from './Link'
    30. import FixiOSBug from './FixiOSBug'
    31. export default {
    32. name: 'SidebarItem',
    33. components: { Item, AppLink },
    34. mixins: [FixiOSBug],
    35. props: {
    36. // route object
    37. item: {
    38. type: Object,
    39. required: true
    40. },
    41. isNest: {
    42. type: Boolean,
    43. default: false
    44. },
    45. basePath: {
    46. type: String,
    47. default: ''
    48. }
    49. },
    50. data() {
    51. this.onlyOneChild = null
    52. return {}
    53. },
    54. methods: {
    55. hasOneShowingChild(children = [], parent) {
    56. if (!children) {
    57. children = [];
    58. }
    59. const showingChildren = children.filter(item => {
    60. if (item.hidden) {
    61. return false
    62. } else {
    63. // Temp set(will be used if only has one showing child)
    64. this.onlyOneChild = item
    65. return true
    66. }
    67. })
    68. // When there is only one child router, the child router is displayed by default
    69. if (showingChildren.length === 1) {
    70. return true
    71. }
    72. // Show parent if there are no child router to display
    73. if (showingChildren.length === 0) {
    74. this.onlyOneChild = { ... parent, path: '', noShowingChildren: true }
    75. return true
    76. }
    77. return false
    78. },
    79. resolvePath(routePath, routeQuery) {
    80. if (isExternal(routePath)) {
    81. return routePath
    82. }
    83. if (isExternal(this.basePath)) {
    84. return this.basePath
    85. }
    86. if (routeQuery) {
    87. let query = JSON.parse(routeQuery);
    88. return { path: path.resolve(this.basePath, routePath), query: query }
    89. }
    90. return path.resolve(this.basePath, routePath)
    91. }
    92. }
    93. }
    94. script>

  • 相关阅读:
    python 字符串类型
    《软件性能测试分析与调优实践之路》第二版-手稿节选-Mysql数据库性能定位与分析
    什么是TypeScript
    java中函数
    LVGL v8学习笔记 | 06 - label控件的使用方法
    Python爬虫实战系列3:今日BBNews编程新闻采集
    点云从入门到精通技术详解100篇-点云滤波算法及单木信息提取(续)
    可视化并理解CNN
    性能之巅 洞悉系统、企业与云计算(完整版)
    EtherCAT主站SOEM-- 0 SOEM下载编译及文件功能介绍
  • 原文地址:https://blog.csdn.net/renkai721/article/details/133163380